• 原生ajax & 跨域问题


    前言

    其实一直对原生ajax和跨域的问题似懂非懂,理解的程度也不是很全面,所以打算整理一下知识点,现在一般交互使用现成的插件,也就是调用封装好的api实现交互,出现的问题对应也有解决的方式,,解决跨域问题也是只知道没有出现跨域问题,如何解决的了解的也不是很透彻,虽然现在可能有些方式用的不是很多了,但是了解清楚还是很重要的

    原生ajax讲解 

    ajax即"Asynchronous Javascript And XML"(异步的JavaScript和XML)
    ajax的核心是XMLHTTPRequest对象(XHR)

    先创建一个xhr对象

    function createXHR(){
      let xhr
      if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest()
      }else if(window.ActiveXObject){
        xhr = new ActiveXObject("Microsoft.XMLHTTP")
      }
      return xhr
    }

    XMLHttpRequest 1级

    xhr对象的主要方法

    void open(String method,String url,Boolean async)
    method:请求方式
    url:请求地址
    async:是否异步,默认为true
    username:可选参数,如果服务器需要验证,该参数指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。
    password:可选参数,验证信息中的密码部分,如果用户名为空则改制将被忽略。
     
    void send(String body)
    body:要发送的数据
     
    void setRequestHeader(String header,String value)
    header:请求头的key
    value:请求头的value
     
    String getAllResponseHeaders()
    获得所有响应头,返回值:响应头数据
     
    String getResponseHeader(String header)
    获取响应头中指定header的值
     
    void abort()
    终止请求

    xhr对象的主要属性

    Number readyState 状态值,可以确定请求/响应过程的当前活动阶段
    0:未初始化。未调用send()方法。
    1:启动。已经调用open()方法,但尚未调用send()方法。
    2:发送。已经调用send()方法,但尚未接收到响应。
    3:接收。已经接收到部分响应数据。
    4:完成。已经接收到全部的响应数据,而且可以在客户端使用了。
     
    Function onreadystatechange 当readyState的值改变时自动触发执行其相应的(回调)函数。
    String responseText 作为相应主体被返回的文本
    XMLDocument responseXML 服务器返回的数据
    Number status 状态码(200/304)
    String statusText 状态文本(OK)

    只要readyState属相的值由一个值变为另一个值,都会触发一次readystatechange事件。也就是说可以用xhr对象监听readystatechange事件,从而在其回调函数中进行逻辑操作。

    xhr.onreadystatechange = function(){
      if(xhr.readyState == 4){
        if(xhr.status >= 200 && xhr.status <= 300 || xhr.status == 304){
          alert(xhr.responseText)
        }else{
          alert(xhr.status)
        }
      }
    }

    XMLHttpRequest 2级

    FormData为序列化表单以及创建与表单格式相同的数据(用于通过xhr传输)提供了遍历。

    let formdata = new FormData()
    formdata.get(key)
    formdata.getAll(key)
    formdata.append(key,value)
    formdata.set(key,value)
    formdata.has(key)
    formdata.delete(key)
    formdata.entries()
    formdata.keys()
    formdata.values()

    超时设定:xhr对象添加了timeout属性,表示请求在等待多少毫秒之后就终止。还可以监听timeout事件。(前提是请求超时终止)

    xhr.timeout = 1000
    xhr.ontimeout = function (){
     
    }

    overrideMimeType()方法,用于重写xhr响应的MIME类型。比如:服务器返回的MIME类型时text/plain,但是数据中实际包含的是XML。根据MIME类型,即使数据时XML,responseXML属性中仍然是null。通过此方法可以保证响应当做XML而非纯文本处理。

     进度事件

    loadstart:在接收到响应数据的第一个字节时触发。
    progress:在接收响应期间持续不间断触发。
    error:在请求发生错误时触发。
    abort:在因为调用abort()方法而终止连接时触发。
    load:在接收到完整的响应数据时触发。
    loadend:在通信完成或者触发error、abort、或load事件后触发。

    实现一个进度指示器

    xhr添加了progress事件,这个事件会在浏览器接收新数据期间周期性触发。而onprogress事件处理程序会接收到一个event对象,其target属性是xhr对象,但包含着三个额外属性:lengthComputable、position和totalSize。其中lengthComputable是一个表示进度信息是否可用的布尔值,position表示已经接收的字节数,totalSize表示根据Content-Length响应头部确定的预期字节数。

    跨域问题

    同源策略:同源策略/SOP(Same Origin Policy)是一种约定,它是浏览器最核心最基础的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。

    跨域:当协议、域名、端口号有一个或多个不同时,又希望可以访问并获取数据的现象称为跨域访问。

    误区:同源策略限制下,访问不到后台服务器的数据,或访问到后台服务器的数据没有返回
    正确:同源策略限制下,可以访问到后台服务器的数据,后台服务器会正常返回数据,只是被浏览器拦截了。

    实现跨域的方式:写几种常见的方式

    jsonp

    只能发送get请求,不支持post、put、delete
    不安全,很容易受到XSS攻击
    function cbFn(data){
      alert(data.name + data.age)
    }
    
    let script = document.createElement('script')
    script.src = 'http://www.zjy.com?callback=cbFn'
    document.body.appendChild(script)
    
    //请求'http://www.zjy.com?callback=cbFn,后端返回的应该是这样的数据格式"cbFn({name:'zhangsan',age:18})"

    使用CORS跨域:个人理解就是后端解决,也不用前端操心

    跨源资源共享/CORS(Cross-Origin Resource Sharing)
    基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应应该成功还是失败。
    设置哪个源可以访问,也可以设置 固定源,参数为 * 时,允许任何人访问,但是不可以和 cookie 凭证的响应头共同使用
    "Access-Control-Allow-Origin": *
     
    想要获取 ajax 的头信息,需设置响应头
    "Access-Control-Allow-Headers":"key"
     
    处理复杂请求的头
    "Access-Control-Allow-Methods": "PUT"

    允许发送 cookie 凭证的响应头
    "Access-Control-Allow-Credentials": true

    允许前端获取哪个头信息
    "Access-Control-Expose-Headers": "key"

    处理 OPTIONS 预检的存活时间,单位 s
    "Access-Control-Max-Age": 10

    使用postMessage实现跨域

    postMessage是H5的新的API,跨文档消息传送(cross-document messaging),简称为XMD。指的是来自不同域的页面见传递消息。
     
    调用方式
    window.postMessage(message,targetOrigin)
    message:发送的数据
    targetOrigin:发送的窗口的域
    在对应的页面中用message事件接收,事件对象中有data、origin、source三个重要信息。
    data:接收到的数据
    origin:接收到数据源的域(数据来自哪个域)
    source:接收到数据源的窗口对象(数据来自哪个窗口对象)

    使用WebSocket实现跨域:WebSocket没有跨域限制

    怎么使用去看WebSocket就可以了不过多说明了
    或是我上面写的实现WebSocket心跳,基本上也用到几乎所有WebSocket中的API。
    WebSocket的API比较简单,用法也相对简单

    vue框架开发出现的跨域问题:这种方式应该是目前开发应用到最多的地方
    可以在vue-cli脚手架config/index.js里面配置proxyTable,使用proxy代理。
    其实这个配置项可以好好研究一下,一般开发的时候也不会注意到,里面还有哪些配置项,具体查一下用法就可以了

    proxyTable:{
        '/api':{ //根据这个字段去匹配
             target:"http://www.zjy.com", //替换成的地址
             changeOrigin:true, //是否跨域
             pathRewrite:{ //重写路径
                "/api":""
             }
        }
    }    

    还有window.name、location.hash与iframe结合解决跨域问题
  • 相关阅读:
    SQL的case when then else end语句的用法
    PR轨道工具
    Power Bi追加查询
    如何在电商平台查看历史价格
    MYSQL执行SQL出现错误:Error Code:1054.Unknown column "字段名" in 'order clause'如何解决
    Python 的基础数据类型
    整数回文转换
    N-城堡问题
    Find The Multiple
    Ecust DIV3 k进制 【暴力不断优化】
  • 原文地址:https://www.cnblogs.com/zhenjianyu/p/12965498.html
Copyright © 2020-2023  润新知