ajax背景ajax对象ajax状态ajax与httpajax请求数据接口同步与异步ajax请求XML数据封装ajax函数artTemplate简介同源策略和跨域请求JSONP

Posted 苦海123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ajax背景ajax对象ajax状态ajax与httpajax请求数据接口同步与异步ajax请求XML数据封装ajax函数artTemplate简介同源策略和跨域请求JSONP相关的知识,希望对你有一定的参考价值。

AJAX简介:

ajax背景:

1.AJAX(Asynchronous javascript And Xml)异步的 JavaScript 和 XML:ajax是浏览器提供的一套API,最早出现在谷歌浏览器,是在浏览器端进行网络编程(发送请求、接收响应)的技术方案。它可以使我们通过JavaScript直接获取服务端最新的内容而不必重新加载页面,让web更接近桌面应用的体验。

2.涉及到ajax操作的界面‘不能’使用文件协议(文件的方式)访问,实际是可以访问的。

3.ajax是一套API,核心提供的类型:XMLHttpRequest,其使用步骤如下:

	<script>
        //  1.创建 XMLHttpRequest 对象,xhr就类似浏览器的作用(发送请求 接收响应)
        var xhr = new XMLHttpRequest(); //xhr变量名可以为其它名,习惯使用xhr;此对象有兼容问题,解决方法如下:
    
        // 解决ajax的IE5-6兼容问题:
        var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXOBject('Microsoft.XMLHTTP');
    
        // 2.打开浏览器输入网址,可以是服务端任何文件,比如 .txt或.php
        xhr.open('GET', 'http://day-03.io/6.Ajax练习/01.ajax的背景/time.php'); //第一个参数为请求方式,第二个参数为请求地址
    
        // 3.发送一个请求,如果是post请求方式,send里面可以传请求体,后面详细讲:
        xhr.send();
    
        // 4.响应,因为客户端永远不知道服务端何时才能返回我们的需求响应,所以,ajax API 采用时间机制(类似通知的方式):
    		xhr.onreadystatechange = function() {
            // 这里this.readyState有三个阶段:2,3,4;写在xhr.open()下面会有状态1的出现,如果需要捕获第一个状态的变化,需要注意代码执行顺序的问题,有0-4五个状态,四个阶段;
            if (this.readyState !== 4) return;//只有状态4表示请求响应已经完成,此时可以对数据进行操作:
          	// 5.看结果
            console.log(this.responseText); //responseText可以接收到响应体,response也可以接收的响应体但是有区别
        };
    </script>

ajax中五种状态四种阶段代表什么:

ajax有五个状态,四种阶段,分别代表如下xhr.readyState的返回值:

	<script>
        var xhr = new XMLHttpRequest();
        console.log(xhr.readyState);
        // => 0:初始化,请求代理对象
        xhr.open('GET', 'time.php');
        console.log(xhr.readyState);
        // => 1:open 方法已经调用,建立一个与服务端特定端口的连接
        xhr.send();
        xhr.addEventListener('readystatechange', function() {
            switch (this.readyState) {
                case 2:
                    // => 2:已经接收到了响应报文的响应头,但是还没有拿到体,this.getAllResponseHeaders()用来获取响应头
                    console.log(this.getResponseHeader('server'));
                    console.log(this.responseText);
                    break;
                case 3:
                    // => 3:正在下载响应报文的响应体,有可能响应体为空,也有可能不完整,这里不能保证响应体数据的完整性
                    console.log(this.responseText);
                    break;
                case 4:
                    // => 4:一切 OK ,整个响应报文已经完整下载下来了,请求体的数据是完整的
                    console.log(this.responseText);
                    break;
            };
        });
    </script>
    
    <script>
        var xhr = new XMLHttpRequest(); //----安装一个浏览器
        console.log(xhr.readyState); //--------------0:初始化请求代理
        xhr.open('GET', 'time.php'); //打开一个浏览器,建立一个与服务端端口的连接
        console.log(xhr.readyState); //--------------1:建立一个与服务端端口的连接
        xhr.send(); //发送请求
        console.log(xhr.readyState); //--------------1
        // 用addEventListener()的方式注册事件:
        xhr.addEventListener('readystatechange', function() {
            // if (this.readyState!==4) return;
            console.log(this.readyState); //-------------4,如果是注释掉上面的if条件,那么这里打印的值为:2,3,4,分别表示:
            // 2:已经接收到响应体的响应头,还没有拿到响应体
            // 3:正在下载响应体中
            // 4:已经下载完一个完整的响应体
            console.log(this.response); //服务端响应的东西,this.responseText也可以拿到响应体
            // 在可以使用this的作用域建议使用this,因为这样可避免沿着作用域链一级一级的向下找,优化了性能。
        });
    </script>

onload事件代替readystatechange事件:

onload事件实现readystatechange事件效果:

	<script>
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'time.php');
        xhr.send(null); 
        xhr.onload = function() { //onload事件可以代替readystatechange事件,但是onload有兼容性问题,因此实际开发中依然不会使用onload
            console.log(this.readyState);
            console.log(this.responseText);
        };
    </script>

ajax遵循http协议:

ajax遵循http协议进行发送请求,在ajax中以post方式进行请求时注意:设置请求头中content-type属性及值,send()中以urlencoded格式设置请求体,如:

	<script>
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'add.php'); //以POST的方式请求一个地址
        //xhr.setRequestHeader('keyA', 'valueA'); //setRequestHeader用来设置一个请求头内容
        // 请求体是 urlencoded 格式的内容,一定要设置请求头中的Content-Type 为'application/x-www-form-urlencoded'才可以正常请求:
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    
        xhr.send('key1=value1&key2=value2'); // 以 urlencoded 格式设置请求体
    </script>

数据接口:

数据接口:能提供特定的能力,有输入有输出,返回数据的地址,如下面服务端代码的URL:users.php即为一个数据接口,详细如下:

服务端代码:

	<?php
      //这里使用假数据做测试,实际开发中可能会从数据库获取数据:
    $data=array(
      array(
        'id'=>1,
        'name'=>'法海',
        'age'=>39
      ),
      array(
        'id'=>2,
        'name'=>'如经',
        'age'=>14
      ),
      array(
        'id'=>3,
        'name'=>'道号',
        'age'=>19
      )
    );
    
    //当收到ajax发送的请求是做出相应的数据返回:
    if(empty($_GET['id'])){
      // 没有传递id返回所有数据,因为http协议中约定报文的内容是字符串,所以需要用json数据格式
      $json = json_encode($data);//==>返回json字符串:[{"id":1,"name":"法海","age":39},{"id":2,"name":"如经","age":14},{"id":3,"name":"道号","age":19}]
      echo $json;
    }else{
      foreach ($data as $item){
        if($item['id']!=$_GET['id']) continue;
        $json = json_encode($item);//==>[{"id":1,"name":"\\u5e08\\u5085","age":39}]
        echo $json;
      };
    };

通过ajax请求数据接口的数据:

	<script>
        var listElement = document.getElementById('list');
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'users.php?id=' + this.id); //这里可以使用?传参请求到具体的值,若不传入参数,则拿回所有数据遍历;在一个readystatechange事件中可以继续new XMLHTTPRequest()请求数据
        xhr.send();
        xhr.onreadystatechange = function() {
            if (this.readyState !== 4) return;
            var data = JSON.parse(this.responseText); //将json字符串转换为json对象
            //通过遍历的方式对数据data进行处理(渲染到页面):
            for (var i = 0; i < data.length; i++) {
                console.log(data[i].id + '--' + data[i].name + '---' + data[i].age); //打印拿到的所有数据
            };
        };
    </script>

responseText和response区别:

responseTexxt返回的是普通字符串的形式的数据,不能通过 xhr.responseType='数据类型’设置返回的数据类型;response可以通过 xhr.responseType='数据类型’设置返回的数据类型。

	<script>
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'test.php');
        xhr.send();
        xhr.responseType = 'json'; //有兼容问题
        xhr.onreadystatechange = function() {
            if (this.readyState === 4) {
                // console.log(this.responseText);
                console.log(this.response);
            };
        };
    </script>

通过ajax发送post请求:

以post方式提交数据,需要注意:如果请求体是urlencoded格式,需要设置请求头的content-type,如:

以post方式通过ajax提交密码和用户名:

	<script>
        // 假设给按钮注册点击事件执行ajax请求提交数据:
        getElement('btn').onclick = function() {
            // 假设获取input中的值并给变量:
            var username = getElement('username').value;
            var password = getElement('password').value;
    
            var xhr = new XMLHttpRequest(); //在js中开启一个浏览器
            xhr.open('POST', 'data.php'); //打开浏览器并访问data.php
    
            //如果请求体是 urlencoded 格式 必须设置请求头为:Content-Type','application/x-www-form-urlencoded'
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            // xhr.send('username=' + username + '&password=' + password),发送请求体,字符串拼接不好操作,推荐使用模板字符串:
            xhr.send(`username=${username}&password=${password}`);
            // 3. 根据服务端的反馈 作出界面提示
            xhr.onreadystatechange = function() {
                if (this.readyState !== 4) return;
                console.log(this.responseText); //若服务端有数据返回,则接收(服务端各个处理的反馈)
            };
        };
    </script>

服务端对用户名和密码做校验并做反馈:

	<?php
    // 判断是否提交数据并做出反馈:
    if(empty($_POST['username'])||empty($_POST['password'])){
      exit('请提交用户名和密码');
    };
    // 接收客户端传过来的数据并给变量:
    $username=$_POST['username'];
    $password=$_POST['password'];
    // 校验数据:通常使用数据库中的数据,这里使用假数据做测试:
    if($username==='admin' && $password==='123'){
      exit('登录成功!');
    };
    exit('用户名或者密码错误');

同步与异步模式:

同步模式:在相同的时间内只能做一件事情,ajax 操作会有楞等的情况,区别在于 send 方法会不会出现等待情况;

异步模式:在相同的时间内可以做不同的事情,比起同步模式,异步处理时间更短,但是时间差异不是很大,一般需要使用console.time()方法进行测试时间。

xhr.open()中的第三个参数async是控制是否开启异步模式,值为布尔值,默认是true则表示异步;

	<script>
        // 同步模式,加载时间长
        var xhrSync = new XMLHttpRequest()
            // open 方法的第三个参数是 async 可以传入一个布尔值,默认为 true
        xhrSync.open('GET', 'time.php', false) //关闭异步模式
        console.time('sync')
        xhrSync.send() //关闭异步模式后,等待请求响应的过程完全完成后再继续
        console.log(xhrSync.responseText)
            // console.log('end request')
        console.timeEnd('sync')
    
    
        // 异步模式,加载时间短
        var xhrSync = new XMLHttpRequest()
            // open 方法的第三个参数是 async 可以传入一个布尔值,默认为 true
        xhrSync.open('GET', 'time.php', true) //打开异步模式,默认是打开的
        console.time('sync')
        xhrSync.send()
        console.log(xhrSync.responseText)
            // console.log('end request')
        console.timeEnd('sync')
    </script>

ajax请求XML数据:

XML数据格式类似存在html标签中的内容,但是标签需要大写,文件后缀名为xml;ajax请求服务端xml数据时,需要指明响应头中content-type为application/xml,如:

ajax请求代码:

	<script>
        // 一般服务端响应一个简单的数据就是一个字符串,如果想要返回一个复杂的数据,一般采用json的格式;但是有很多老项目采用xml的方式存数据,此时也是需要获取数据的,如:
        // ajax请求XML格式的数据:
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'xml.php');
        xhr.send();
        xhr.onreadystatechange = function() {
            if (this.readyState !== 4) return;
            // this.responseXML 是专门用于获取服务端返回XML数据的,操作方式就是通过DOM(节点)的方式操作,但是需要服务端响应头中的 Content-Type 必须是 application/xml
            // header('Content-Type: application/xml');---需要服务端响应头中的 Content-Type 必须是 application/xml
            console.log(this.responseXML.documentElement.children[0].innerHTML)
            console.log(this.responseXML.documentElement.getElementsByTagName('name')[0])
        }
    </script>

服务端XML数据:

	<?php
    header('Content-Type: application/xml');//告知响应头中响应文档类型为xml
    ?>
    <?xml version="1.1" encoding="utf-8"?>
    <person>
      <name>小明</name>
      <age>14</age>
      <gender></gender>
    </person>
    <!-- 上面不能有空行,否则报错 -->

封装ajax函数:

实际开发中使用ajax获取数据的地方很多,为了节省开发成本,一般是将ajax封装成一个函数,使用时调用即可,我封装了一个名为ajax的AJAX数据请求函数,其中参数解释为:

method:必须,请求方式,

url:必须,请求路径

askbody:可选参数,当不需要向服务端传入参数时,可以给null占位,但是不能不写

callback:必须,一个用来处理响应数据的回调函数,回调函数中的参数即为响应结果

	<script>
        function ajax(method, url, askbody, callback) {
            method = method.toUpperCase(); //当调用者输入的请求方式为小写字母时转大写
            var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXOBject('Microsoft.XMLHTTP'); //解决兼容问题
    
            //默认请求体是字符串形式的,当调用者输入的是对象形式时,需要转换为字符串形式:
            if (typeof askbody === 'object') {
                var arr = []; //定义一个空数组用来对askbody进行拆解再拼接为字符串
                for (var key in askbody) {
                    var value = askbody[key]; //通过遍历的的方式将请求体对象中的键拿到,并使用[键]的方式将对应的值拿到给变量value
                    arr.push(key + '=' + value); //将键和值作为一组元素追加到数组中
                };
                askbody = arr.join('&'); //将数组每个元素之间用&符号分割后转换为字符串形式,并重新给askbody,join可以将数组转化为字符串,括号中加参数则表示给每个元素之间添加的字符。
            };
    
            //如果是以get方式请求:将url和askbody进行拼接:
            if (method === 'GET') {
                url += '?' + askbody;
            };
    
            xhr.open(method, url);
    
            //需要以post请求时,定义一个变量data接收请求体;当为get方式请求时,因为下面send中传入null或者不传,因此这里需要将data变量提升到整个函数作用域并初始值为null:
            var data = null;
            if (method === 'POST') { //当以post请求时,需要传入请求体,如下:
                data = askbody; //将上面处理好的askbody赋值给data变量供下面send中使用
                xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //当为post请求时,必须设置请求头中的Content-Type的值为application/x-www-form-urlencoded,且此代码要放到open的后面,否则会报错
            };
    
            xhr.send(data);
    
            xhr.addEventListener('readystatechange', function() {<

以上是关于ajax背景ajax对象ajax状态ajax与httpajax请求数据接口同步与异步ajax请求XML数据封装ajax函数artTemplate简介同源策略和跨域请求JSONP的主要内容,如果未能解决你的问题,请参考以下文章

AJAX 状态值(readyState)与状态码(status)详解

AJAX 状态值(readyState)与状态码(status)详解

Ajax状态值及状态码

AJAX 状态值(readyState)与状态码(status)详解

AJAX 状态值(readyState)与状态码(status)详解

325 AJAX介绍,XMLHttpRequest对象,实现Ajax的异步交互步骤,服务器端通信状态