• Ajax,跨域,nrm


    一、ajax 原理 和 使用

    ajax,即在不重新加载整个网页的情况下,对网页的某部分进行更新。

    下面演示ajax 的实现原理

    配置:

    cd ajax
    

    参考:http://www.expressjs.com.cn/starter/generator.html

    express --view=ejs myapp
    cd myapp
    npm install
    

    1、完整的ajax流程:

    (1)、 创建XMLHttpRequest对象

    var xhr = new XMLHttpRequest();
    

    (2)、准备发送

     xhr.open('get', './01check.js?username='+uname+'&password='+pw,true);
    

    (3)、执行发送动作

     xhr.send(null);
    

    (4)、监听response 回调函数

    onreadystatechange 事件:每当 readyState 改变时,就会触发 onreadystatechange 事件。

    2、代码逻辑

    index.js 路由

    ......
    router.get('/api/one',(req,res,next)=>{
      res.json({
          status:200,
          result:'this is one.....'
      })
    });
    
    
    /* GET home page. */
    router.get('/one', function(req, res, next) {
      res.render('index1', { title: 'Express' });
    })
    ...........
    

    index.ejs:

    <body>
    <button id="send">发送1个请求</button>
    <script>
      var btn = document.getElementById('send');
      btn.addEventListener('click',function () {
         // 使用原生的ajax 技术,发送一个网络请求
          // 1.创建XMLHttpRequest对象
          var xhr;
          if(window.XMLHttpRequest){
              xhr = new XMLHttpRequest();
          }else {
              xhr = new ActiveXObject('Microsoft.XMLHTTP');
          }
    
          // 2.准备发送
          /*
           参数1: 请求方式 (get/post)
           参数2: 请求url
           参数3: 是否异步
        */
          xhr.open('get','http://localhost:3000/api/one',true);
    
          // 3. 发送
        xhr.send();
    
          // 4. 监听服务器的响应
          // 一旦服务器响应回来之后, 就会执行这个函数
          xhr.onreadystatechange = function () {
              console.log(xhr.readyState);
              if(xhr.readyState === 4){  // 代表服务器已经给了响应, 不代表响应成功
                  if(xhr.status === 200){
                      console.log(xhr.response);
                  }
              }
          }
    
      });
    </script>
    </body>
    
    // 结果:
    /*
    2
    3
    4
    {"status":200,"result":"this is one....."}
    */
    


    index.js 路由:

    router.get('/api/two',(req,res,next)=>{
        console.log(req.query);
        res.json({
            status:200,
            result:'this is two.....'
        })
    });
    
    
    router.get('/two', function(req, res, next) {
        res.render('index2', { title: 'Express' });
    });
    

    index2.ejs

    <body>
    <input id="account" type="text" name="account">
    <input id="pwd" type="text" name="pwd">
    <button id="send">发送一个请求</button>
    <script>
        window.onload=function () {
    
            var btn = document.getElementById('send');
            btn.onclick = function () {
                // 使用原生的ajax 技术,发送一个网络请求
                // 1.创建XMLHttpRequest对象
                var xhr;
                if(window.XMLHttpRequest){
                    xhr = new XMLHttpRequest();
                }else {
                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
                }
    
                // 从页面获取需要传递的数据
                var userName = document.getElementById('account').value;
                var pwd = document.getElementById('pwd').value;
    
                // 2.准备发送
                /*
                 参数1: 请求方式 (get/post)
                 参数2: 请求url
                 参数3: 是否异步
              */
                // 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
                xhr.open('get', 'http://localhost:3000/api/two?account=' + account + '&pwd=' + pwd + '&random=' + getRandomStr(), true);
    
                // 3. 发送
                xhr.send();
    
                // 4. 监听服务器的响应
                // 一旦服务器响应回来之后, 就会执行这个函数
                xhr.onreadystatechange = function () {
                    // 5. 处理响应的数据 (对方说话)
                    console.log(xhr.readyState);
                    if(xhr.readyState === 4){  // 代表服务器已经给了响应, 不代表响应成功
                        if(xhr.status === 200){
                            console.log(xhr.response);
                        }
                    }
                }
            }
        }
    
    
        function getRandomStr() {
            return Math.random() + (new Date().getTime())
        }
    </script>
    
    </body>
    

    前端打印:

    2
    3
    4
    {"status":200,"result":"this is two....."}
    

    服务端打印:

    { account: '[object HTMLInputElement]',
      pwd: '123456',
      random: '1547356096169.2708' }
    GET /api/two?account=[object%20HTMLInputElement]&pwd=123456&random=1547356096169.2708 200 8.824 ms - 42
    
    


    封装ajax:

    AjaxTool.js:

    (function (window) {
        function AjaxTool() {}
    
        AjaxTool.ajaxRequest = function (url, paramObj, timeout, successCallBack, errorCallBack) {
            // 1.创建XMLHttpRequest对象
            var xhr;
            if(window.XMLHttpRequest){
                xhr = new XMLHttpRequest();
            }else {
                xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
    
    
            // 2.准备发送
            /*
             参数1: 请求方式 (get/post)
             参数2: 请求url
             参数3: 是否异步
          */
            // 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
            var params_str = getStrWithObj(paramObj);
            var uri_str = url + '?' + params_str;
            // 转码
            var codeURI = encodeURI(uri_str)
            xhr.open('get', codeURI, true);
    
    
            // 3. 发送
            xhr.send();
    
            // 4. 监听服务器的响应
            xhr.onreadystatechange = function () {
                // 5. 处理响应的数据
                console.log(xhr.readyState);
                if(xhr.readyState === 4){  // 代表服务器已经给了响应, 不代表响应成功
                    if(xhr.status === 200){
                        successCallBack(xhr);
                    }else {
                        errorCallBack();
    
                    }
                }
            }
    
            // 5. 控制请求的时间
            var timer;
            if(timeout > 0){
                timer = setTimeout(function () {
                    // 取消ajax  请求
                    xhr.abort();
                },timeout);
            }
    
        }
        /*
        * 把对象转换成字符串
        * */
        function getStrWithObj(paramsObj) {
            var arr = [];
            for(var k in paramsObj){
                var str = k + '=' + paramsObj[k];
                arr.push(str);
            }
            arr.push('random='+ getRandomStr());
            return arr.join('&');
        }
    
        /*
        返回一个随机数
        * */
        function getRandomStr() {
            return Math.random() + (new Date().getTime())
        }
    
        window.AjaxTool = AjaxTool;
    })(window);
    

    index3.ejs:

    <body>
    <input id="account" type="text" name="account">
    <input id="pwd" type="text" name="pwd">
    <button id="send">发送一个请求</button>
    <script>
        window.onload=function () {
    
            var btn = document.getElementById('send');
            btn.onclick = function () {
                // 使用原生的ajax 技术,发送一个网络请求
                // 1.创建XMLHttpRequest对象
                var xhr;
                if(window.XMLHttpRequest){
                    xhr = new XMLHttpRequest();
                }else {
                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
                }
    
                // 从页面获取需要传递的数据
                var userName = document.getElementById('account').value;
                var pwd = document.getElementById('pwd').value;
    
                // 2.准备发送
                /*
                 参数1: 请求方式 (get/post)
                 参数2: 请求url
                 参数3: 是否异步
              */
                // 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
                xhr.open('get', 'http://localhost:3000/api/two?account=' + account + '&pwd=' + pwd + '&random=' + getRandomStr(), true);
    
                // 3. 发送
                xhr.send();
    
                // 4. 监听服务器的响应
                // 一旦服务器响应回来之后, 就会执行这个函数
                xhr.onreadystatechange = function () {
                    // 5. 处理响应的数据 (对方说话)
                    console.log(xhr.readyState);
                    if(xhr.readyState === 4){  // 代表服务器已经给了响应, 不代表响应成功
                        if(xhr.status === 200){
                            console.log(xhr.response);
                        }
                    }
                }
            }
        }
    
        function getRandomStr() {
            return Math.random() + (new Date().getTime())
        }
    </script>
    
    </body>
    

    3、简单版原生 post方式

    <body>
    <input id="account" type="text" name="account">
    <input id="pwd" type="text" name="pwd">
    <button id="send">发送一个请求</button>
    <script>
        window.onload=function () {
            var btn = document.getElementById('send');
            btn.onclick = function () {
                // 1. 获取数据
                var account = document.getElementById('account').value;
                var pwd = document.getElementById('pwd').value;
    
    
                // 第一步
                var xhr = new XMLHttpRequest();
                // 第二步
                xhr.open('post','http://localhost:3000/api/four',true)
                // 第三步
                xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                xhr.send('account='+account + '&pwd=' + pwd);
    
                // 第四步
                xhr.onreadystatechange = function () {
                    console.log(xhr.readyState);
                    console.log(xhr.status);
                    if(xhr.readyState === 4 && xhr.status === 200){
                        console.log(xhr.responseText);
                    }else {
                        console.log('请求失败');
                    }
                }
    
            }
        }
    
    </script>
    
    </body>
    

    4、ajax 完整封装

    (function(window){
        function AjaxTool(){}
        AjaxTool.ajaxRequest = function(params,successCallBack,errorCallBack){
            // 0. 获取参数
            var requestType = params['requestType'] || 'get';
            var url = params['url'];
            var paramsObj = params['paramsObj'];
            var timeout = params['timeout'];
            console.log(params);
            // 1.创建XMLHttpRequest对象 (找到一个电话)
            var xhr;
            if(window.XMLHttpRequest){
                xhr =new XMLHttpRequest();
            }else{
                xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
    
            // 2.判断请求方式
            if(requestType.toLowerCase() === 'get'){
                var codeURI = encodeURI(url + '?' + getStrWithObject(paramsObj));
                xhr.open('get',codeURI,true);
                xhr.send();
            }else if(requestType.toLowerCase() === 'post'){
                // 请求体
                var codeParam = encodeURI(getStrWithObject(paramsObj));
                xhr.open('post',url,true);
                xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                console.log(codeParam);
                xhr.send(codeParam);
    
            }
    
            // 3. 监听服务器响应
            xhr.onreadystatechange = function(){
                // 3.1 处理响应数据
                if(xhr.readyState === 4){
                    // 4 代表服务器给响应了,并不代表响应成功
                    if(xhr.status === 200){
                        successCallBack(xhr);
                        // 清除定时器
                        clearTimeout(timer);
                    }else{
                        errorCallBack();
                    }
                }
            }
    
    
            // 4. 控制响应时间
            var timer;
            if(timeout > 0){
                timer = setTimeout(function(){
                    // 取消ajax请求
                    xhr.abort();
                },timeout);
            }
    
    
        }
    
    
    
        /*
        返回一个随机数
        */
        function getRandomStr(){
            return	Math.random() + (new Date().getTime());
        }
    
    
        /*
        把对象转成字符串
        */
        function getStrWithObject(paramsObj){
            var arr = [];
            for(var key in paramsObj){
                var str = key + '=' + paramsObj[key];
                arr.push(str)
            }
            arr.push('random=' + getRandomStr())
            return arr.join('&');
        }
        window.AjaxTool = AjaxTool;
    })(window)
    

    index5.ejs:

    <body>
    <input id="account" type="text" name="account">
    <input id="pwd" type="text" name="pwd">
    <button id="send">发送一个请求</button>
    <script src="../js/AjaxTool.js"></script>
    <script>
        window.onload=function () {
            var btn = document.getElementById('send');
            btn.onclick = function () {
                // 1. 获取数据
                var account = document.getElementById('account').value;
                var pwd = document.getElementById('pwd').value;
    
                // 2. 处理数据
                var paramsObj = {
                    'account':account,
                    'pwd':pwd
                }
    
                var params = {
                    'requestType':'post',
                    'url':'http://localhost:3000/api/five',
                    'paramsObj':paramsObj,
                    'timeout':2000
                }
    
                AjaxTool.ajaxRequest(params,function (xhr) {
                    console.log('成功' + xhr.responseText);
                },function () {
                    console.log('失败');
                });
    
            }
        }
    
    </script>
    
    </body>
    

    index.js 服务端路由文件:

    router.get('/five',(req,res,next)=>{
        res.render('index5')
    });
    
    router.post('/api/five',(req,res,next)=>{
        console.log(req.body);
        res.json({
            status:200,
            result:'this is five...method:post..'
        })
    });
    

    访问:http://localhost:3000/five

    输入admin 123456 ,然后提交

    前端打印:成功{"status":200,"result":"this is five...method:post.."}

    服务端打印:{ account: 'admin', pwd: '123123', random: '1547522571613.208' }

    5、用 jquery 进行 ajax 请求

    三方封装的是最完善的,我们用三方封装好的即可,但是对ajax原生的执行的大致逻辑知道一些比较好。

    index6.ejs:

    <body>
    <form action="http://localhost:3000/api/six" method="post">
        <input id="account" type="text" name="account">
        <input id="pwd" type="text" name="pwd">
        <input id="send" type="submit" value="请求">
    </form>
    <script src="/js/jquery.js"></script>
    <script>
        $('form').on('submit', function () {
            console.log($(this).serialize());  //account=admin&pwd=123456
            $.ajax({
                url: $(this).attr('action'),
                type: $(this).attr('method'),
                data: $(this).serialize(),
                success: function (data) {
                    console.log(data);  //{status: 200, result: "this is six...."}
                }
            });
    
            // 阻止默认事件
            return false;
        });
    </script>
    

    服务端:

    router.post('/api/six',(req,res,next)=>{
        console.log(req.body);
        res.json({
            status:200,
            result:'this is six....'
        })
    });
    

    二、跨域

    1、什么是跨域

    同源策略:

    2、解决方案:

    jsonp
    document.domain+iframe :只有主域名相同的情况下方可使用此方法
    location.hash + iframe
    window.name + iframe
    window.postMessage 
    flash等第三方插件
    

    3、跨域演示

    express-generator 快速创建一个应用的骨架server,然后在服务端index.js 路由中

    router.get('/', function(req, res, next) {
      // res.render('index', { title: 'Express' });
        console.log(`收到客户端的请求: ${req.url}`);
        res.end('end');
    });
    

    在本地新创建一个页面,不要通过和 server 端口一致

    <body>
    <button id="send">点我</button>
    <script src="js/AjaxTool.js"></script>
    <script>
        window.onload = function () {
            var btn = document.getElementById('send');
            btn.onclick = function () {
                var paramObj = {
                    'name':'zhangsan',
                    'pwd':'123'
                };
                var params = {
                 'requestType' : 'get',
                 'url' : 'http://localhost:3000/',
                 'paramObj' : paramObj,
                 timeout : 2000
                };
    
                // 发起请求
                AjaxTool.ajaxRequest(params,function (xhr) {
                    console.log('success...'+ xhr.responseText);
                },function () {
                    console.log('failed.....');
                })
            }
        }
    </script>
    
    </body>
    

    结果:

    服务端还是收到请求了,打印:

    收到客户端的请求: /?name=zhangsan&pwd=123&random=1547690599507.3115
    GET /?name=zhangsan&pwd=123&random=1547690599507.3115 - - ms - -

    客户端打印如下图:

    4、jsonp 解决跨域问题

    • jsonp跨域必须前后端联合支持

    • jsonp只支持get不支持post

    (1) 演示1

    路由:

    router.get('/',function (req,res,next) {
        console.log(`收到客户端的请求: ${req.url}`);
        var data = JSON.stringify({
            status_code:200,
            result:{
              name:'张三',
              age:19,
              friend:['李四','王五','赵六']
            }
        });
        res.end('getData('+data+')');
    });
    

    前端页面:

    <body>
    <script>
        function getData(data) {
            console.log(data);
        }
    </script>
    <script src="http://localhost:3000/"></script>
    </body>
    

    通过 script 引入,来跨域请求,这个是可行的,同样的方式,还有 css标签的引入

    1547692058626

    (2) 封装

    路由:

    router.get('/',function (req,res,next) {
        console.log(`收到客户端的请求: ${req.url}`);
        var data = JSON.stringify({
            status_code:200,
            result:{
              name:'张三',
              age:19,
              friend:['李四','王五','赵六']
            }
        });
        console.log(`${req.query.callback}(${data})`);
        res.end(`${req.query.callback}(${data})`);
    });
    

    前端:

    <body>
    <script>
    
    jsonp({
        url: 'http://localhost:3000/',
        data: '',
        success: function (data) {
            console.log(11111);
            console.log(data);
        }
    });
    jsonp({
        url: 'http://localhost:3000/',
        data: '',
        success: function (data) {
            console.log(22222);
    
            console.log(data);
        }
    });
    
    /*
    * 1、让函数名称不一致
    * 2、调用完成后删除
    * */
    function jsonp(option) {
        // 1. 将用户通过对象的命名空间传递进来的函数 挂载到全局
        var callbackName = 'hello_' + Math.random().toString().substr(2);
        window[callbackName] = function (data) {
            option.success(data);
            // 删除 script 标签 ,多次调用后 script 太多了,在这里删除掉
            document.body.removeChild(script);
        };
    
        // 1. 处理url的拼接
        option.url = option.url + '?callback=' + callbackName;
        // 2. 创建script标签
        var script = document.createElement('script');
        script.src = option.url;
        document.body.appendChild(script);
    
    
        /*说明: 拼接完url后,url 会带上函数的名称,服务端根据url 取得函数名称,然后返回的时候
            res.end(`${req.query.callback}(${data})`); 
        * */
    }
    
    </script>
    </body>
    

    前端代码注释:

    加断点可以查看执行流程,首先 jsonp({})执行,接着到下面的 function jsonp({}),在下面的 function jsonp() 里面, window[callbackName] = function (data) {} ,在这里只是声明了函数,并且是全局的,但是并没有调用,里面的东西是在后来服务端 响应后调用的,并接着调用 了 里面的 option.success(data) 的函数,因为这个时候,服务端返回的时候把参数data 也传回来了 res.end(${req.query.callback}(${data})); 。所以接着执行了上面的 jsonp({}) 里面的 success:function(){data} 的函数。

    执行结果:

    三、nrm

    什么是nrm:

    install:

    $ npm install -g nrm

    查看有哪些源:

    $ nrm ls
    
    * npm -----  https://registry.npmjs.org/
      cnpm ----  http://r.cnpmjs.org/
      taobao --  https://registry.npm.taobao.org/
      nj ------  https://registry.nodejitsu.com/
      rednpm -- http://registry.mirror.cqupt.edu.cn
      skimdb -- https://skimdb.npmjs.com/registry
    

    选择镜像源:

    $ nrm use cnpm  //switch registry to cnpm
    
        Registry has been set to: http://r.cnpmjs.org/
    

    注意:每次安装包的时候,依然是使用 npm 命令来安装。

  • 相关阅读:
    Android.mk简介
    signal函数的原型声明void (*signal(int signo, void (*fun(int))))(int)分析
    关于fork()函数的精辟分析
    [Ubuntu]win10卸载ubuntu
    [Shell]清空文件内容 | 使用curl进行post请求
    【Shell】在字符串中引用变量
    [Jenkins]视图
    [Jenkins]执行git push命令报错fatal: could not read Username forxxx| 配置jenkins使用ssh方式连接git
    [MAC]Permission denied, please try again.
    [Shell] 函数的应用
  • 原文地址:https://www.cnblogs.com/friday69/p/10262358.html
Copyright © 2020-2023  润新知