1.AJAX基础

1.1.AJAX简介

AJAX即 “Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
通过在后台与服务器进行数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
2005年初,许多事件使得Ajax被大众所接受。Google在它著名的交互应用程序中使用了异步通讯,如Google、Google地图、Google搜索框架等。

1.2.第三方数据接口

在我们学习AJAX之前,我们首先得有一个服务器为我们提供数据。但是,我们还没有学到服务器端编程,所以现在暂时不能开发服务器端应用程序。
我们可以使用一些其他公司,在网络上给我们提供的一些数据API(数据接口),作为服务器端,为我们提供数据。常用的第三方数据接口有:

  1. 百度API
  2. 聚合数据API
  3. 天行数据API
  4. 极速数据API
  5. … …

下面案例中,需要使用 “天行数据API” 与 “聚合数据API” ,所以,需要大家先去注册。

  1. 天行数据:https://www.tianapi.com/
    申请 “天气预报” 接口:https://www.tianapi.com/apiview/72 (可直接跨域访问)
  2. 聚合数据:https://www.juhe.cn/

    申请 “新闻头条” 接口:https://www.juhe.cn/docs/api/id/235 (不可直接跨域访问)

    1.3.AJAX实例

    XMLHttpRequest是 Ajax 应用程序的核心,它是一个 JavaScript 对象 。
    当客户端发出请求时,请求数据发送给XMLHttpRequest而不是直接发送给服务器。而且请求是异步发送的。并且,服务器不在将数据直接返回给客户端浏览器,而是返回给XMLHttpRequest对象。
    也就是说:XMLHttpRequest可以实现客户端与服务器只进行数据层面的交互,而不是视图层面的交互。

    1. //创建XMLHttpRequest核心对象
    2. let xhr = new XMLHttpRequest();
    3. //open()方法来完成Http请求(get方式)
    4. xhr.open("get", "http://api.tianapi.com/txapi/ncovcity/index?key=自己的key");
    5. //向服务器发送请求
    6. xhr.send(null);
    7. //使用onreadystatechange事件监听XMLHttpRequest对象状态。
    8. xhr.onreadystatechange = function() {
    9. //readyState属性代表了 XMLHttpRequest对象的五种状态。4状态为响应内容接收并解析完成
    10. if (xhr.readyState == 4) {
    11. //http请求会返回一个状态码。200为请求成功。
    12. if (xhr.status == 200) {
    13. //xhr.responseText就是服务器端返回的数据
    14. console.log(xhr.responseText);
    15. }
    16. }
    17. };

    readyState属性代表了 XMLHttpRequest对象的状态;而onreadystatechange事件能够监听XMLHttpRequest对象的状态变化。XMLHttpRequest对象的五种状态:

    • 0(未初始化)还没有调用send()方法
    • 1(载入)已调用send()方法,已建立服务器连接
    • 2 (载入完成)send()方法执行完成,已经接收到全部响应内容
    • 3 (交互)正在解析响应内容
    • 4 (完成)响应内容解析完成,可以在客户端调用了

1.4.AJAX的异步特性

  1. //先声明一个变量,用来接收ajax请求的响应数据
  2. let result;
  3. let xhr = new XMLHttpRequest();
  4. xhr.open("get", "http://api.tianapi.com/txapi/ncovcity/index?key=自己的key");
  5. xhr.send(null);
  6. xhr.onreadystatechange = function() {
  7. if (xhr.readyState == 4) {
  8. if (xhr.status == 200) {
  9. //在这里接收响应数据
  10. result = xhr.responseText;
  11. }
  12. }
  13. };
  14. //输出接收的响应数据
  15. console.log(result);

很遗憾,上面代码会输出:undefined

注意:

  1. ajax是异步请求。也就是说:发送请求后,程序并不会等待响应结果,而是会继续往下运行。
  2. 因此,当 result = xhr.responseText; 这段代码还没有执行完时,就已经执行 console.log(result); 了。
  3. 所以,必须要在ajax状态监听的回调函数中,才能保证获取响应数据。

2.axios框架

在实际开发中,我们都使用一些封装好的ajax框架。 优秀的ajax框架很多,这里我们选用axios框架。原因是:Vue官方推荐使用的就是axios框架。 axios框架中文官网:http://www.axios-js.com/

2.1.get方式与post方式请求

在学习axios之前,首先要知道:http请求方式有两种:get方式、post方式。

  1. get方式:显式提交。 将表单内容经过编码之后 ,通过URL发送, 即将提交参数写在URL地址的后面。 使用get方式发送时有字符长度的限制(因为get方式请求的参数是放在请求头中的),不安全。
  2. post方式:隐式提交。 将表单的内容通过http发送,即不将提交参数写在URL地址的后面,而是封装在请求体中。 post没有字符长度的限制,安全。(因为post方式请求的参数是放在请求体中的)

    注意:

    1. 在早期的、前后端不分离的开发模式中,大量使用表单提交、超链接提交等。那么、表单提交、超链接提交默认都是get方式。只有在表单中明确设置 method=”post” 时,才是post提交、
    2. 现在的前后端分离开发模式中,已经不再使用表单提交、超链接提交等,而都是使用 ajax 提交。

2.2.axios的get方式请求

  1. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  2. <script>
  3. //get方式请求,请求参数直接写在url的后面
  4. axios.get('http://api.tianapi.com/txapi/ncovcity/index?key=自己的key')
  5. .then(function(response) {
  6. console.log(response);
  7. })
  8. .catch(function(error) {
  9. console.log(error);
  10. });
  11. </script>

2.3.axios的post方式请求

  1. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  2. <script>
  3. //将json数据转成URI编码,并解析为xxx=xxx&xxx=xxx形式
  4. function transformRequest(data) {
  5. let ret = '';
  6. for (let it in data) {
  7. ret += encodeURIComponent(it)+'='+encodeURIComponent(data[it])+'&';
  8. }
  9. return ret;
  10. }
  11. //post方式请求,请求参数不写在url的后面(需要将json对象参数转码,服务器端才能识别)
  12. axios.post('http://api.tianapi.com/txapi/ncovcity/index', transformRequest({
  13. key: '自己的key'
  14. }))
  15. .then(function(response) {
  16. console.log(response);
  17. })
  18. .catch(function(error) {
  19. console.log(error);
  20. });
  21. </script>

2.4.axios响应数据结构

axios响应的数据结构是一个json对象,此json对象结构如下:

  1. {
  2. // `data` 由服务器提供的响应
  3. data: {},
  4. // `status` 来自服务器响应的 HTTP 状态码
  5. status: 200,
  6. // `statusText` 来自服务器响应的 HTTP 状态信息
  7. statusText: 'OK',
  8. // `headers` 服务器响应的头
  9. headers: {},
  10. // `config` 是为请求提供的配置信息
  11. config: {},
  12. // 'request' 请求信息
  13. request: {}
  14. }

2.5.axios的全局配置

可以在全局配置axios的一些属性,那么这些配置就将被用在各个请求中。

  1. //设置axios的基础url部分
  2. axios.defaults.baseURL = 'https://api.example.com';

2.6.axios拦截器

我们还可以在请求或响应之前,拦截请求和响应。

  1. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  2. <script>
  3. //请求拦截器
  4. axios.interceptors.request.use(function(config) {
  5. console.log('在发送请求之前做些什么');
  6. return config;
  7. }, function(error) {
  8. console.log('对请求错误做些什么');
  9. return Promise.reject(error);
  10. });
  11. //响应拦截器
  12. axios.interceptors.response.use(function(response) {
  13. console.log('在响应之前做些什么');
  14. return response;
  15. }, function(error) {
  16. console.log('对响应错误做点什么');
  17. return Promise.reject(error);
  18. });
  19. axios.get('http://api.tianapi.com/txapi/ncovcity/index?key=自己的key')
  20. .then(function(response) {
  21. console.log(response);
  22. })
  23. .catch(function(error) {
  24. console.log(error);
  25. });
  26. </script>

注意:修改请求url使之成为一个错误的url,运行后,会触发拦截 “请求之前” 和 “响应错误” 。

3.在Vue-cli中使用axios

  1. 添加axios模块:

    cnpm install axios --save        //添加axios模块
    cnpm install qs --save           //添加qs模块(用于处理post请求的参数解析)
    
  2. 添加成功后,在package.json文件中就可以看到:

    "dependencies": {
     "axios": "^0.19.2",
     "core-js": "^3.6.5",
     "qs": "^6.9.4",
     "vue": "^2.6.11",
     "vue-router": "^3.2.0",
     "vuex": "^3.4.0"
    },
    
  3. 在main.js文件中导入这些模块

    import axios from 'axios'
    import qs from 'qs'
    //设置axios的基础url部分
    axios.defaults.baseURL = 'http://api.tianapi.com/';
    //将axios挂载到vue实例上,使用时就可以 this.$axios 这样使用了
    Vue.prototype.$axios = axios;
    //将qs挂载到vue实例上,使用时就可以 this.$qs 这样使用了
    Vue.prototype.$qs = qs;
    
  4. 在About.vue文件中书写代码:

    <template>
    <div class="about">
     <h1>全国省市疫情</h1>
     <table>
         <tr>
             <th>省市</th>
             <th>累计确诊</th>
             <th>累计治愈</th>
             <th>现有确诊</th>
             <th>累计死亡</th>
         </tr>
         <tr v-for="item in yq.newslist">
             <td></td>
             <td></td>
             <td></td>
             <td></td>
             <td></td>
         </tr>
     </table>
    </div>
    </template>
    <script>
     export default{
         name:'About',
         data(){
             return {
                 yq:{}
             }
         },
         created() {
             /*
             //get方式
             this.$axios.get('txapi/ncovcity/index',{
                 params:{
                     key:'自己的key'
                 }
             }).then(function(response) {
                 console.log(response.data);
             }).catch(function(error) {
                 console.log(error);
          });
             */
             //post方式
             this.$axios.post('txapi/ncovcity/index',this.$qs.stringify({
                 key:'e0a32a8ea4275e9dbe2628d03bb91f3e'
             })).then((response)=> {
                 this.yq = response.data;
                 console.log(this.yq);
             }).catch((error)=> {
                 console.log(error);
             });
         }
     }
    </script>
    <style scoped>
     table {
         width: 100%;
         text-align: center;
         border-bottom: solid 2px #DDD;
         /* 合并边框 */
         border-collapse: collapse;
     }
     td,th {
         border-bottom: solid 1px #DDD;
         height: 40px;
     }
    </style>
    

    4.在Vue-cli中实现跨域访问

    4.1.什么是跨域访问

    4.1.1.同源策略

    同源策略,它是由Netscape提出的一个著名的安全策略。它是浏览器最核心也最基本的安全策略。 网络协议、服务器的IP地址、端口都相同,即为同源。否则,上面三个中有一个不同,即为不同源。
    07.AJAX的使用 - 图1

    4.1.2.跨域访问

    当一个客户端访问服务器端时,如果客户端的协议、IP、端口三者之间的任一个,与服务器端的协议、IP、端口不同时,即为跨域访问。

    注意:为了安全,AJAX默认不允许跨域访问

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    axios.get('http://v.juhe.cn/toutiao/index?type=top&key=自己的key')
        .then(function(response) {
            console.log(response);
        })
        .catch(function(error) {
            console.log(error);
        });
</script>

运行上面代码,在浏览器控制台中会出现 “跨域访问” 错误。 07.AJAX的使用 - 图2 Access-Control-Allow-Origin 访问控制允许源

4.1.3.解决AJAX跨域问题

我们现在的开发模式是前后端分离,也就是前端是一个工程,部署在客户端机器上; 而服务器端是另一个工程,部署在服务器机器上。这就必然要进行跨域访问。但是,AJAX默认不允许跨域访问,如何解决呢?
通常有两种解决方案:

  1. 服务器端设置允许跨域访问; 比如:CORS(跨域资源共享)代理方式
  2. 前端通过代理进行跨域访问;比如:Vue-cli自带的跨域代理方式

    注意:

    1. 上面案例中,天行数据接口的服务器端就允许跨域访问。而聚合数据接口的服务器,就不允许跨域访问。
    2. 这里我们使用Vue-cli给我们提供的代理方式实现跨越访问;
    3. 后续课程中,我们还要学习CORS方式实现服务器端允许跨域访问。

4.2.使用Vue-cli实现跨域访问

  1. 在Vue-cli配置文件中书写代理跨域配置:

    module.exports = {
     devServer:{
         port:8080,
         proxy: {
             '/juheNews':{
                 target:'http://v.juhe.cn/toutiao/index',    //需要跨域的url
                 ws:true,                                    //代理webSocket
                 changeOrigin:true,                          //允许跨域
                 pathRewrite:{
                     '^/juheNews':''                         //重写路径
                 }
             }
         }
     }
    }
    

    我们知道同源策略只是在浏览器中存在,不存在于服务器中。因此我们可以将需要跨域请求的地址转发给Vue-cli自带服务器,然后委托服务器去请求信息。(常见的有node代理、nginx转发等。)

  2. 在vue组件中进行访问:

    <script>
     export default{
         name:'About',
         data(){
             return {}
         },
         created() {
             this.$axios.get('/juheNews?type=top&key=自己的key')
                 .then(function(response) {
                     console.log(response.data);
                 })
                 .catch(function(error) {
                     console.log(error);
                 });   
         }
     }
    </script>
    

    注意:访问时使用代理url:/juheNews?type=top&key=自己的key

课后作业

1、JS原生AJAX实现步骤是什么?
2、请写出axios框架两种请求方式可以写的语法结构。
3、跨域访问原理是什么,请简单概述?
4、简述XMLHttpRequest对象的五种状态?
5、简述ajax的异步请求特性?
[

](https://null_688_6639.gitee.io/javase/15Vue/06.%E7%AC%AC%E5%85%AD%E7%AB%A0Vue-cli%E8%84%9A%E6%89%8B%E6%9E%B6.html)