1. 什么是同源策略及限制:

  • 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
    源:协议、域名、端口(默认 80)三个构成一个源。 不是一个源的文档无法去操作另一个源的资源。
  • 限制:

    - Cookie、LocalStorage 和 IndexDB 
    - Dom 无法获得 
    - Ajax 不能发送
    

2. 前后端如何通信:

  1. Ajax 同源下
  2. WebSocket 不限制
  3. CORS 支持跨源通信 也支持同源通信

3. 如何创建Ajax

XMLHttpRequest 对象的工作流程
兼容性处理(IE 浏览器的处理)
事件的触发条件
事件的触发顺序
if(opt.url){
    // 声明XMLHttpRequest 对象的工作流程
    var xhr = XMLHttpRequest ? new XMLHttpRequest () : new window.ActiveXObject('Microsoft.XMLHTTP');
    var data = opt.data,
        url = opt.url,
        type = opt.type.toUpperCase(),
        dataArr = [];
    for (var k in data) {
        dataArr.push(k + '=' + data[k]);
    }
    if (type === 'GET') {
        url = url +'?' + dataArry.join('&');
        xhr.open(type,url.replace(/\?$/g,''),true);
        xhr.send();
    }
    if (type === 'POST') {
        xhr.open(type,url,true);
        xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        xhr.send(dataArry.join('&'));
    }
    // 监听它成功失败
    xhr.onload = function () {
        // 200:304:重定向,利用本地缓存
        if (xhr.status === 200 || xhr.status === 304 ) { // 媒体资源加206
            var res;
            if (opt.success && opt.success instanceof Function) {
                res = xhr.responseText;
                if(typeof res === 'String') {
                    res = JSON.parse(res);
                    opt.success.call(xhr,res);
                }
            }
        } else {
            if (opt.error && opt.error instanceof Function) {
                opt.error.call(xhr,res); 
                }
            }
        }
    }

4. 跨域通信的几种方式:

  1. JSONP
  2. Hash 「url 地址中 # 后面的东西是 Hash, Hash改变页面不改变」「url 地址中 ?后面的东西是Search,Search 改变页面刷新」
  3. postMessage「Html5 新增的,同源策略限制跨域通信,但实际的开发业务中我们又需要用到跨域通信,所以出现这种方式」
  4. WebSocket「不受同源策略限制」
  5. CORS 「支持跨域通信的 Ajax ,浏览器在识别你用Ajax发送跨域请求时,浏览器会在 HTTP 头中加一个 Origin,如果没有浏览器就会拦截」

代码实例:


var util = {};

 /**
  * [function 在页面中注入js脚本]
  * @param  {[type]} url     [description]
  * @param  {[type]} charset [description]
  * @return {[type]}         [description]
  */
 util.createScript = function (url, charset) {
    var script = document.createElement('script');
    script.setAttribute('type', 'text/javascript');
    charset && script.setAttribute('charset', charset);
    script.setAttribute('src', url);
    script.async = true;
    return script;
};

 /**
  * [function jsonp]
  * @param  {[type]} url      [description]
  * @param  {[type]} onsucess [description]
  * @param  {[type]} onerror  [description]
  * @param  {[type]} charset  [description]
  * @return {[type]}          [description]
  */
util.jsonp = function (url, onsuccess, onerror,charset) {
    var callbackName = util.getName('tt_player'); // 加载script标签的形式
    window[callbackName] = function () { // 以这个回调名称注册一个全局的函数
        if (onsuccess && util.isFunction(onsuccess)){
            onsuccess(arguments[0]);
        }
    };
    var script = util.createScript(url + '&callback' + callbackName,charset);
    script.onload = script.onreadystatechange = function () {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            script.onload = script.onreadystatechange = null;
            // 移除该script的 DOM 对象
            if (script.parentNode) {
                script.parentNode.removeChild(script);
            }
            // 删除函数或变量
            window[callbackName] = null;
        }
    };
    script.onerror = function () {
        if (onerror && util.isFunction(onerror)) {
            onerror();
        }
    };
    document.getElementsByTagName('head')[0].appendChild(script);
};


// AJAX
util.extend(opt,options);
if(opt.url){
    // 声明XMLHttpRequest 对象的工作流程
    var xhr = XMLHttpRequest ? new XMLHttpRequest () : new window.ActiveXObject('Microsoft.XMLHTTP');
    var data = opt.data,
        url = opt.url,
        type = opt.type.toUpperCase(),
        dataArr = [];
    for (var k in data) {
        dataArr.push(k + '=' + data[k]);
    }
    if (type === 'GET') {
        url = url +'?' + dataArry.join('&');
        xhr.open(type,url.replace(/\?$/g,''),true);
        xhr.send();
    }
    if (type === 'POST') {
        xhr.open(type,url,true);
        xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        xhr.send(dataArry.join('&'));
    }
    // 监听它成功失败
    xhr.onload = function () {
        // 200:客户端请求成功 304:重定向,利用本地缓存
        if (xhr.status === 200 || xhr.status === 304 ) { // 媒体资源加206
            var res;
            if (opt.success && opt.success instanceof Function) {
                res = xhr.responseText;
                if(typeof res === 'String') {
                    res = JSON.parse(res);
                    opt.success.call(xhr,res);
                }
            }
        } else {
            if (opt.error && opt.error instanceof Function) {
                opt.error.call(xhr,res); 
                }
            }
        }
    }
    
export default util;
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>通信类</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js"></script>
</head>

<body>
    <script>
        // 创建ajax【参考网址】https://segmentfault.com/a/1190000006669043
        // 参考jsonp.js
    </script>

    <script src="http://www.abc.com/?data=name&callback=jsonp"></script>
    <script type="text/javascript">
        // jsonp({
        //     data: {
        //
        //     },
        // });
    </script>
    <script type="text/javascript">
        /**
         * 跨域通信的几种方法
         */

        // jsonp工作原理,参考jsonp.js


        // 利用hash,场景是当前页面 A 通过iframe或frame嵌入了跨域的页面 B
        // 在A中伪代码如下:
        var B = document.getElementsByTagName('iframe');
        B.src = B.src + '#' + 'data';
        // 在B中的伪代码如下
        window.onhashchange = function () {
            var data = window.location.hash;
        };

        // postMessage
        // 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
        Bwindow.postMessage('data', 'http://B.com'); // B 窗口下的 window 
        // 在窗口B中监听
        Awindow.addEventListener('message', function (event) {
            console.log(event.origin); // http://A.com
            console.log(event.source); // Awindow
            console.log(event.data); // data
        }, false);

        // Websocket【参考资料】http://www.ruanyifeng.com/blog/2017/05/websocket.html

        var ws = new WebSocket('wss://echo.websocket.org'); // ws加密 wss非加密

        ws.onopen = function (evt) {
            console.log('Connection open ...');
            ws.send('Hello WebSockets!');
        };

        ws.onmessage = function (evt) {
            console.log('Received Message: ', evt.data);
            ws.close();
        };

        ws.onclose = function (evt) {
            console.log('Connection closed.');
        };

        // CORS【参考资料】http://www.ruanyifeng.com/blog/2016/04/cors.html
        // url(必选),options(可选)
        // 新的 API
        fetch('/some/url/', {
            method: 'get',
        }).then(function (response) {

        }).catch(function (err) {
            // 出错了,等价于 then 的第二个参数,但这样更好用更直观
        });
    </script>
</body>

</html>

License

  • 可以拷贝、转发,但是必须提供原作者信息,同时也不能将本项目用于商业用途。

spoiler
94 声望8 粉丝

因为在奔跑 所以耳边有风🍃


« 上一篇
面向对象类
下一篇 »
渲染机制