1 vue-resource发送ajax

  • 实现数据的请求,then指定成功回调,真正的数据是在result.body中放着,除了 vue-resource 之外,还可以使用 axios 的第三方包实现实现数据的请求
  • axios是一个基于promise的HTTP库,可以用在浏览器和node.js中
  • 下载vue-resource,引用<script src="./lib/vue-resource-1.3.4.js"></script>。先写vue再写resource
  • 直接在页面中,通过script标签,引入 vue-resource 的脚本文件,引用的先后顺序是:先引用 Vue 的脚本文件,再引用 vue-resource 的脚本文件

1.1 3种方式post,get,jsonp请求接口API

  • get一个参数,要请求的URL地址
  • post三个参数
    参数一,要请求的URL地址
    参数二,要发送的数据对象
    参数三,指定post提交的编码类型为application/x-www-form-urlencoded
  • jsonp一个参数,要请求的URL地址,then后面是成功之后的函数
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getInfo() { // 发起get请求
          //  当发起get请求之后, 通过 .then 来设置成功的回调函数
          this.$http.get('http://vue.studyit.io/api/getlunbo').then(function (result) {
            // 通过 result.body 拿到服务器返回的成功的数据
            // console.log(result.body)
          })
        },
        postInfo() { // 发起 post 请求   application/x-wwww-form-urlencoded
          //  手动发起的 Post 请求,默认没有表单格式,所以,有的服务器处理不了
          //  通过 post 方法的第三个参数, { emulateJSON: true } 设置 提交的内容类型 为 普通表单数据格式
          this.$http.post('http://vue.studyit.io/api/post', {}, { emulateJSON: true }).then(result => {
            console.log(result.body)
          })
        },
        jsonpInfo() { // 发起JSONP 请求
          this.$http.jsonp('http://vue.studyit.io/api/jsonp').then(result => {
            console.log(result.body)
          })
        }
      }
    });
  </script>

1.2 Jsonp

代码解析:
(1)首先要引入resource库
(2)全局配置根地址:Vue.http.options.root = ‘http://47.89.21.179:8080/’;
(3)全局启用 emulateJSON 选项,post不用再强调:Vue.http.options.emulateJSON = true;
(4)打开页面的时候就要自动操作访问数据库加载数据,所以要把请求数据库加载的函数放在created函数中,越早约好。
(5)通过 $http 获取到的数据,都在 result.body 中放着
(6)result.status等于0表示返回成功,拿到数据在result.body中,通过调用result.body.变量就可以访问数据库的信息了。
(7)展示数据,用get,不用带参数;
(8)add数据,要用post,post(地址,参数,全局设置好就不用设置的emulateJSON)
(9)del数据,要用get,带要删除哪个的id参数,get(地址/+id)。接口文档应该会说明。

<!DOCTYPE html>
<html lang="en">
 
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <script src="./lib/vue-resource-1.3.4.js"></script>
  <link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
</head>
 
<body>
  <div id="app">
    <div class="panel panel-primary">
      <div class="panel-heading">
        <h3 class="panel-title">添加品牌</h3>
      </div>
      <div class="panel-body form-inline">
 
        <label>
          title:
          <input type="text" v-model="title" class="form-control">
        </label>
 
        <input type="button" value="添加" @click="add" class="btn btn-primary">
      </div>
    </div>
 
 
 
    <table class="table table-bordered table-hover table-striped">
      <thead>
        <tr>
          <th>Id</th>
          <th>Name</th>
          <th>Ctime</th>
          <th>Operation</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in list" :key="item.id">
          <td>{{item.title}}</td>
          <td>{{item.url}}</td>
          <td>{{item.className}}</td>
          <td>
            <a href="" @click.prevent="del(item.id)">删除</a>
          </td>
        </tr>
      </tbody>
    </table>
 
 
  </div>
 
  <script>
    // 如果我们通过全局配置了,请求的数据接口 根域名,则 ,在每次单独发起 http 请求的时候,请求的 url 路径,应该以相对路径开头,前面不能带 /  ,否则 不会启用根路径做拼接;
    Vue.http.options.root = 'http://47.89.21.179:8080/';
    // 全局启用 emulateJSON 选项
    Vue.http.options.emulateJSON = true;
 
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        title: '',
        list: [ // 存放所有品牌列表的数组
        ]
      },
      created() { // 当 vm 实例 的 data 和 methods 初始化完毕后,vm实例会自动执行created 这个生命周期函数
        this.getAllList()
      },
      methods: {
        getAllList() { // 获取所有的品牌列表 
          // 分析:
          // 1. 由于已经导入了 Vue-resource这个包,所以 ,可以直接通过  this.$http 来发起数据请求
          // 2. 根据接口API文档,知道,获取列表的时候,应该发起一个 get 请求
          // 3. this.$http.get('url').then(function(result){})
          // 4. 当通过 then 指定回调函数之后,在回调函数中,可以拿到数据服务器返回的 result
          // 5. 先判断 result.status 是否等于0,如果等于0,就成功了,可以 把 result.message 赋值给 this.list ; 如果不等于0,可以弹框提醒,获取数据失败!
 
          this.$http.get('api/getmenus').then(result => {
            // 注意: 通过 $http 获取到的数据,都在 result.body 中放着
            var result = result.body
            if (result.status === 0) {
              // 成功了
              this.list = result.message
            } else {
              // 失败了
              alert('获取数据失败!')
            }
          })
        },
        add() {  // 添加品牌列表到后台服务器
          // 分析:
          // 1. 听过查看 数据API接口,发现,要发送一个 Post 请求,  this.$http.post
          // 2. this.$http.post() 中接收三个参数:
          //   2.1 第一个参数: 要请求的URL地址
          //   2.2 第二个参数: 要提交给服务器的数据 ,要以对象形式提交给服务器 { name: this.name }
          //   3.3 第三个参数: 是一个配置对象,要以哪种表单数据类型提交过去, { emulateJSON: true }, 以普通表单格式,将数据提交给服务器 application/x-www-form-urlencoded
          // 3. 在 post 方法中,使用 .then 来设置成功的回调函数,如果想要拿到成功的结果,需要 result.body
 
          /* this.$http.post('api/addproduct', { name: this.name }, { emulateJSON: true }).then(result => {
            if (result.body.status === 0) {
              // 成功了!
              // 添加完成后,只需要手动,再调用一下 getAllList 就能刷新品牌列表了
              this.getAllList()
              // 清空 name 
              this.name = ''
            } else {
              // 失败了
              alert('添加失败!')
            }
          }) */
 
          this.$http.post('api/addproduct', { title: this.title }).then(result => {
            if (result.body.status === 0) {
              // 成功了!
              // 添加完成后,只需要手动,再调用一下 getAllList 就能刷新品牌列表了
              this.getAllList()
              // 清空 name 
              this.title  = ''
            } else {
              // 失败了
              alert('添加失败!')
            }
          })
        },
        del(id) { // 删除品牌
          this.$http.get('api/delproduct/' + id).then(result => {
            if (result.body.status === 0) {
              // 删除成功
              this.getAllList()
            } else {
              alert('删除失败!')
            }
          })
        }
      }
    });
  </script>
</body>
 
</html>

2 什么是前后端交互模式

  • 接口调用方式:原生ajax、基于jQuery的ajax、 fetch、axios
  • URL地址格式:
    1 传统形式的 URL
    • 格式:schema://host:port/path?query#fragment

      schema:协议。例如http、https、ftp等
      host:域名或者IP地址
      port:端口,http默认端口80,可以省略
      path:路径,例如/abc/a/b/c
      query:查询参数,例如uname=lisi&age=12
      fragment:锚点(哈希Hash),用于定位页面的某个位置
      
    • 符合规则的URL

      http://www.itcast.cn
      http://www.itcast.cn/java/web
      http://www.itcast.cn/java/web?flag=1
      http://www.itcast.cn/java/web?flag=1#function
      

2 Restful形式的 URL

  • HTTP请求方式

    GET 查询
    POST 添加
    PUT 修改
    DELETE 删除
    
  • 符合规则的URL地址

    http://www.hello.com/books GET
    http://www.hello.com/books POST
    http://www.hello.com/books/123 PUT
    http://www.hello.com/books/123 DELETE
    

2.1 Promise的相关概念和用法

2.1.1 异步调用

  • JavaScript的执行环境是「单线程」
  • 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程
  • 异步模式可以一起执行多个任务
  • JS中常见的异步调用
    • 定时任何
    • ajax
    • 事件函数
  • 多次异步调用的依赖分析:
    • 多次异步调用的结果顺序不确定
    • 异步调用结果如果存在依赖需要嵌套
      在这里插入图片描述

2.1.2 Promise 概述

  • Promise 是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息。
  • 使用 Promise 主要有以下好处:
    • 可以避免多层异步调用嵌套问题(回调地狱)
    • Promise对象提供了简洁的API,使得控制异步操作更加容易

2.1.3 Promise 基本用法

  • 实例化 Promise 对象,构造函数中传递函数,该函数中用于处理异步任务
  • resolvereject两个参数用于处理成功和失败两种情况,并通过 p.then 获取处理结果
var p = new Promise(function(resolve, reject) {
       // 成功时调用 resolve()
       // 失败时调用 reject ()
});
p.then(funciton(ret){
      // 从resolve得到正常结果
}, function(ret){
      // 从reject得到错误信息
});
<script type="text/javascript">
    // 1. Promise基本使用: 我们使用new来构建一个Promise  Promise的构造函数接收一个参数,是函数,
    //	并且传入两个参数: resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数
   var p = new Promise(function(resolve, reject){
     //2. 这里用于实现异步任务  setTimeout
     setTimeout(function(){
       var flag = false;
       if(flag) {
         //3. 正常情况
         resolve('hello');
       }else{
         //4. 异常情况
         reject('出错了');
       }
     }, 100);
   });
   //  5 Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数 
   //  在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了  
   p.then(function(data){
     console.log(data)
   },function(info){
     console.log(info)
   });
 </script>

2.1.4 基于Promise发送Ajax请求

  • 处理原生Ajax
function queryData()(
 return new Promise(function(resolve,reject){
   var xhr = new XMLHttpRequest () ;
   xhr.onreadystatechange= function(){
      if(xhr.readyState !=4) return ;
      if (xhr.status == 200){
         resolve(xhr.responseText)
        }else{
           reject('出错了');
       }
}
    xhr.open( 'get', '/data');
    xhr.send(null);
j)
  • 发送多次ajax请求
queryData()
  .then(function(data){
    return queryData() ;
})
 .then(function(data){
    return queryData(;
})
 .then(function(data){
   return queryData();
})
 <script type="text/javascript">
    /*基于Promise发送Ajax请求*/
    function queryData(url) {
     #   1.1 创建一个Promise实例
      var p = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
          if(xhr.readyState != 4) return;
          if(xhr.readyState == 4 && xhr.status == 200) {
            # 1.2 处理正常的情况
            resolve(xhr.responseText);
          }else{
            # 1.3 处理异常情况
            reject('服务器错误');
          }
        };
        xhr.open('get', url);
        xhr.send(null);
      });
      return p;
    }
	# 注意:  这里需要开启一个服务 
    # 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
    queryData('http://localhost:3000/data')
      .then(function(data){
        console.log(data)
        #  1.4 想要继续链式编程下去 需要 return  
        return queryData('http://localhost:3000/data1');
      })
      .then(function(data){
        console.log(data);
        return queryData('http://localhost:3000/data2');
      })
      .then(function(data){
        console.log(data)
      });
  </script>
  • then参数中的函数返回值
    • 1.返回 Promise实例对象:返回的该实例对象会调用下一个then
    • 2.返回普通值:返回的普通值会直接传递给下一个then,通过then 参数中函数的参数接收该值

2.1.5 Promise常用的API

  • 1.实例方法
    • p.then() 得到异步任务的正确结果
    • p.catch() 获取异常信息
    • p.finally()成功与否都会执行(尚且不是正式标准)
queryData ()
  .then(function(data) {
         console.log(data);
})
  .catch(function(data){
        console.log(data);
})
  .finally(function(){
       console.log(finished")
});
 <script type="text/javascript">
    /*Promise常用API-实例方法 */
    // console.dir(Promise);
    function foo() {
      return new Promise(function(resolve, reject){
        setTimeout(function(){
          // resolve(123);
          reject('error');
        }, 100);
      })
    }
    // foo()
    //   .then(function(data){
    //     console.log(data)
    //   })
    //   .catch(function(data){
    //     console.log(data)
    //   })
    //   .finally(function(){
    //     console.log('finished')
    //   });

    // --------------------------
    // 两种写法是等效的
    foo()
      .then(function(data){
        # 得到异步任务正确的结果
        console.log(data)
      },function(data){
        # 获取异常信息
        console.log(data)
      })
      # 成功与否都会执行(不是正式标准) 
      .finally(function(){
        console.log('finished')
      });
  </script>
  • 2.对象方法
    • Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果。Promise.all方法接受一个数组作参数,数组中的对象(p1、p2、p3)均为promise实例(如果不是一个promise,该项会被用Promise.resolve转换为一个promise)。它的状态由这三个promise实例决定
    • Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果。Promise.race方法同样接受一个数组作参数。当p1, p2, p3中有一个实例的状态发生改变(变为fulfilledrejected),p的状态就跟着改变。并把第一个改变状态的promise的返回值,传给p的回调函数。
Promise.all([p1,p2,p3]).then((result) =>{
     console.log(result)
})
Promise.race([p1,p2,p3]).then((result) =>{
     console.log(result)
} )
<script type="text/javascript">
    /* Promise常用API-对象方法 */
    // console.dir(Promise)
    function queryData(url) {
      return new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
          if(xhr.readyState != 4) return;
          if(xhr.readyState == 4 && xhr.status == 200) {
            // 处理正常的情况
            resolve(xhr.responseText);
          }else{
            // 处理异常情况
            reject('服务器错误');
          }
        };
        xhr.open('get', url);
        xhr.send(null);
      });
    }

    var p1 = queryData('http://localhost:3000/a1');
    var p2 = queryData('http://localhost:3000/a2');
    var p3 = queryData('http://localhost:3000/a3');
     Promise.all([p1,p2,p3]).then(function(result){
       //   all 中的参数  [p1,p2,p3]   和 返回的结果一 一对应["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
       console.log(result) //["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
     })
    Promise.race([p1,p2,p3]).then(function(result){
      // 由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将被丢弃。
      console.log(result) // "HELLO TOM"
    })
  </script>

2.2 fetch 进行接口调用

  • Fetch API是新的ajax解决方案 Fetch会返回Promise
  • fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象
  • fetch(url, options).then()

2.2.1 fetch 概述

1.基本特性

  • 更加简单的数据获取方式,功能更强大、更灵活,可以看做是xhr的升级版
  • 基于Promise实现

2.语法结构

fetch(url).then(fn2)
          .then(fn3)
          ...
          .catch(fn)

3.基本用法

fetch('/abc') . then (data=>{
      return data.text();
}).then(ret=>{
     // 注意这里得到的才是最终的数据
     console.log(ret);
})
<script type="text/javascript">
    /*
      Fetch API 基本用法
      	fetch(url).then()
     	第一个参数请求的路径   Fetch会返回Promise   所以我们可以使用then 拿到请求成功的结果 
    */
    fetch('http://localhost:3000/fdata').then(function(data){
      // text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
      return data.text();
    }).then(function(data){
      //   在这个then里面我们能拿到最终的数据  
      console.log(data);
    })
  </script>

2.2.2 fetch请求参数

1.fetch API 中的 HTTP 请求:fetch(url, options).then()

  • method(String):HTTP请求方法, 默认为GET(GET、POST、PUT、DELETE)。-需要在 options 对象中 指定对应的 method method:请求使用的方法 。
  • post 和 普通 请求的时候 需要在options 中 设置 请求头 headers 和 body
    • body(String):HTTP的请求参数
    • headers(Object): HTTP的请求头,默认为{}
fetch('/abc'{
     method:'get'
}).then(data=>{
     return data.text();
}).then(ret=>{
     // 注意这里得到的才是最终的数据
    console.log(ret);
})

2.GET请求方式的参数传递
在这里插入图片描述
3.DELETE请求方式的参数传递
在这里插入图片描述
4.POST请求方式的参数传递
在这里插入图片描述
注:还有JSON格式的
5.PUT请求方式的参数传递

<script type="text/javascript">
        /*
              Fetch API 调用接口传递参数
        */
       #1.1 GET参数传递 - 传统URL  通过url  ? 的形式传参
       /*后台接口:
       app.get('/books',(req,res){
           res.send('传统URL传参参数'+req.query.id)
       })
       */
        fetch('http://localhost:3000/books?id=123', {
            	# get 请求可以省略不写 默认的是GET 
                method: 'get'
            })
            .then(function(data) {
            	# 它返回一个Promise实例对象,用于获取后台返回的数据
                return data.text();
            }).then(function(data) {
            	# 在这个then里面我们能拿到最终的数据  
                console.log(data)
            });

      #1.2  GET参数传递  restful形式的URL  通过/ 的形式传递参数  即  id = 456 和id后台的配置有关
       /*后台接口:
       app.get('/books/:id',(req,res){
           res.send('Restful形式的URL传参参数'+req.params.id)
       })
       */
        fetch('http://localhost:3000/books/456', {
            	# get 请求可以省略不写 默认的是GET 
                method: 'get'
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data)
            });

       #2.1  DELETE请求方式参数传递      删除id  是  id=789
        fetch('http://localhost:3000/books/789', {
                method: 'delete'
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data)
            });

       #3.1 POST请求传参
        /*后台接口:
       app.post('/books/',(req,res){
           res.send('POST请求传参参数'+req.body.uname)
         })
       */
        fetch('http://localhost:3000/books', {
                method: 'post',
            	# 3.1  传递数据 
                body: 'uname=lisi&pwd=123',
            	#  3.2  设置请求头 
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data)
            });

       #3.2 POST请求传参
        fetch('http://localhost:3000/books', {
                method: 'post',
                body: JSON.stringify({
                    uname: '张三',
                    pwd: '456'
                }),
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data)
            });

        #4 PUT请求传参     修改id 是 123/*后台接口:
       app.put('/books/:id',(req,res){
           res.send('PUT请求传参参数'+req.params.id+'--'+req.body.uname+'req.body.pwd')
       })
       */
        fetch('http://localhost:3000/books/123', {
                method: 'put',
                body: JSON.stringify({
                    uname: '张三',
                    pwd: '789'
                }),
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data)
            });
    </script>

2.2.3 fetchAPI 中 响应格式

用fetch来获取数据,如果响应正常返回,我们首先看到的是一个response对象,其中包括返回的一堆原始字节,这些字节需要在收到后,需要我们通过调用方法将其转换为相应格式的数据,比如JSONBLOB或者TEXT等等

  • text():将返回体处理成字符串类型
  • json():返回结果和JSON.parse(responseText)一样
fetch('/abc' then(data=>{
     // return data.text();
     return data.json()}).then (ret=>{
    console.log(ret);
})

后台接口:

app.get(/json', (req, res)=> {
   res.json({
       unane: 'lisi',
       age: 13,
       gender: male
    });
  })
fetch('http://localhost:3000/json').then(function(data){
      // return data.json();   //  将获取到的数据使用 json 转换对象
      return data.text(); //  //  将获取到的数据 转换成字符串 
    }).then(function(data){
      // console.log(data.uname)
      // console.log(typeof data)
      var obj = JSON.parse(data);
      console.log(obj.uname,obj.age,obj.gender)
    })

2.3 axios 进行接口调用

axios 是一个专注于网络请求的库!,官网: https://www.axios-http.cn

2.3.1 基本特性

1.特征:

  • 基于promise用于浏览器和node.js的http客户端
  • 支持浏览器和node.js
  • 支持promise
  • 能拦截请求和响应
  • 自动转换JSON数据
  • 能转换请求和响应数据

2.用法:

  • 安装axios包:
    npm install axios
    import axios from 'axios' 哪个文件需要用到就在哪个文件中引入

  • 或者:链接: github地址.下载压缩包->打开dist里axios.js(测试用),开发用axios.min.js,移动js目录下->引入
    <script src="js/axios.js"></script>

axios.get('/adata')
         .then (ret=>{
          // data属性名称是固定的,用于获取后台响应的数据
         console.log(ret.data)
})

2.3.2 axios 的三种写法

(1)第一种写法

// 使用CommonJS语法引入
import axios from "axios";

axios.get("/query?name=tom").then(res => {
    console.log(res.data);
});

axios.get('/query?name=tom').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

(2)第二种写法

axios.get('/query', {
   // URL 中的查询参数
    params: {
        name: 'tom'
    }
}).then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

(3)第三种写法

axios({
  method: 'get', // 请求方式
  url: '/query', // 请求的地址
  // URL 中的查询参数
  params: {
    name: 'tom'
  },
 // 请求体参数
  data: {}
}).then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

2.3.3 axios 的常用API

  • get : 查询数据
  • post: 添加数据
  • put: 修改数据
  • delete:删除数据
  • 1 get和 delete请求传递参数
    • 通过传统的url 以 ? 的形式传递参数
    • restful 形式传递参数
    • 通过params 形式传递参数
  • 2 post 和 put 请求传递参数
    • 通过选项传递参数
    • 通过 URLSearchParams 表单传递参数
# 1. 发送get 请求 
   axios.get('http://localhost:3000/adata').then(function(ret){ 
     #  拿到 ret 是一个对象      所有的对象都存在 ret 的data 属性里面
     // 注意data属性是固定的用法,用于获取后台的实际数据
     // console.log(ret.data)
     console.log(ret)
   })
   # 2.  get 请求传递参数
   # 2.1  通过传统的url  以 ? 的形式传递参数,后台接口 req.query. id
   axios.get('http://localhost:3000/axios?id=123').then(function(ret){
     console.log(ret.data)
   })
   # 2.2  restful 形式传递参数 ,后台接口 req.params. id
   axios.get('http://localhost:3000/axios/123').then(function(ret){
     console.log(ret.data)
   })
   # 2.3  通过params  形式传递参数 ,后台接口 req.query. id
   axios.get('http://localhost:3000/axios', {
     params: {
       id: 789
     }
   }).then(function(ret){
     console.log(ret.data)
   })
   #3 axios delete 请求传参     传参的形式和 get 请求一样
   axios.delete('http://localhost:3000/axios', {
     params: {
       id: 111
     }
   }).then(function(ret){
     console.log(ret.data)
   })

   # 4  axios 的 post 请求
   # 4.1  通过选项传递参数  后台req.body.uname
   axios.post('http://localhost:3000/axios', {
     uname: 'lisi',
     pwd: 123
   }).then(function(ret){
     console.log(ret.data)
   })
   # 4.2  通过 URLSearchParams  传递参数 
   var params = new URLSearchParams();
   params.append('uname', 'zhangsan');
   params.append('pwd', '111');
   axios.post('http://localhost:3000/axios', params).then(function(ret){
     console.log(ret.data)
   })

	#5  axios put 请求传参   和 post 请求一样 
   axios.put('http://localhost:3000/axios/123', {
     uname: 'lisi',
     pwd: 123
   }).then(function(ret){
     console.log(ret.data)
   })

2.3.4 axios 的响应结果

响应结果的主要属性

  • data: 实际响应回来的数据
  • headers:响应头信息
  • status:响应状态码
  • statusText:响应状态信息
axios.post('/axios-json').then(ret=>{
          console.log(ret.data.uname)
     })
 后台接口:res.json({
          uname:'lisi',
          age:'14'
       })

2.3.5 参数配置

axios({
  // 请求的服务器 URL
  url: '/user',

  // 创建请求时使用的方法
  method: 'get', // 默认是 get

  // 将自动加在 url 前
  baseURL: 'https://some-domain.com/api/',

  // 在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],
  
  // 在传递给 then/catch 前,修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // 自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // 与请求一起发送的 URL 参数
  params: {
    ID: 12345
  },

  // 用于 params 的序列化的函数
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // 请求发送的数据,适用于 PUT, POST, 和 PATCH
  // 在没有设置 transformRequest 时,必须是以下类型之一:
  // string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // 浏览器专属:FormData, File, Blob
  // Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // 指定请求超时毫秒数(0 表示无超时时间)
  timeout: 1000,

  // 表示跨域请求时是否需要使用凭证,默认 false
  withCredentials: false, 

  // 允许自定义处理请求,常用用于测试
  adapter: function (config) {
    /* ... */
  },

  // 表示应该使用 HTTP 基础验证,并提供凭据,该参数会在 headers 设置 Authorization
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

  // 表示服务器响应的数据类型,
  // 支持类型:arraybuffer, blob, document, json(默认), text, stream
  responseType: 'json', 

  // 用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', 

  //  xsrf token 值的 HTTP 头的名称
  xsrfHeaderName: 'X-XSRF-TOKEN', 

  // 上传处理进度事件
  onUploadProgress: function (progressEvent) {
  },

  // 下载处理进度事件
  onDownloadProgress: function (progressEvent) {
  },

  // 响应内容的最大尺寸
  maxContentLength: 2000,

  // 定义对于给定的HTTP 响应状态码。
  validateStatus: function (status) {
    return status >= 200 && status < 300; 
  },

  // 定义在 node.js 中 follow 的最大重定向数目,为0将不会 follow 任何重定向
  maxRedirects: 5, 

  // 在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: : {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  }
}).then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

2.3.6 axios 全局配置,Vue的使用

#  配置公共的请求头 默认地址 
axios.defaults.baseURL = 'https://localhost:3000/';
axios.get('axios-json').then(...)   简写了
#  配置 超时时间
axios.defaults.timeout = 2500;
#  配置公共的请求头
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
# 配置公共的 post 的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

(1)main.js引入axios:

import axios from 'axios'
// 设置请求的根路径
axios.defaults.baseURL = "http://localhost:8088"
//将axios包挂载到vue的原型对象上,使得vue的每一个组件能够通过this访问$http,从而发起ajax请求
Vue.prototype.$http = axios

(2)在组件中不需要import,直接使用

  • 通过$http.post发起请求,/user/findAll为请求路径,后面的为请求需要携带的参数,其返回值为promise对象包含的数据很多

  • 另外:通过await简化promise,awai只能用在async修饰的方法中,返回的是具体的响应对象data{},其中有六个属性都是axios封装好的,属性中只有data属性是服务器返回的真实数据。

this.$http.get("/user/findAll").then((response)=>{
        this.tableData = response.data
      })

2.3.7 axios 拦截器

  • 请求拦截器
    • 请求拦截器的作用是在请求发送前进行一些操作
      • 例如在每个请求体里加上token,统一做了处理如果以后要改也非常容易
  • 响应拦截器
    • 响应拦截器的作用是在接收到响应后进行一些操作
      • 例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页
//  1. 请求拦截器 
   axios.interceptors.request.use(function(config) {
     console.log(config.url)
     // 1.1  任何请求都会经过这一步   在发送请求之前做些什么 
     config.headers.mytoken = 'nihao';
     // 1.2  这里一定要return   否则配置不成功  
     return config;
   }, function(err){
      //1.3 对请求错误做点什么    
     console.log(err)
   })
   //2. 响应拦截器 
   axios.interceptors.response.use(function(res) {
     //2.1  在接收响应做些什么  
     var data = res.data;
     return data;
   }, function(err){
    //2.2 对响应错误做点什么  
     console.log(err)
   })

2.4 async/await方式调用接口

  • async/await 是ES7引入的新语法,方便异步操作让异步代码看起来、表现起来更像同步代码
  • async作为一个关键字放到函数前面(任何一个async函数都会隐式返回一个promise
  • await关键字只能在使用async定义的函数中使用(可以得到异步的结果)
    • ​ await后面可以直接跟一个 Promise实例对象,不用写.then,直接赋给response
    • ​ await函数不能单独使用

2.4.1 async 基础用法

  async function queryData(id) {
      var ret = await axios.get('/data');
       return ret;
    }
   queryData.then(ret=>{
      console.log(ret)
    })
# 1.  async 基础用法
    # 1.1 async作为一个关键字放到函数前面
	async function queryData() {
      # 1.2 await关键字只能在使用async定义的函数中使用      await后面可以直接跟一个 Promise实例对象
      var ret = await new Promise(function(resolve, reject){
        setTimeout(function(){
          resolve('nihao')
        },1000);
      })
      // console.log(ret.data)
      return ret;
    }
	# 1.3 任何一个async函数都会隐式返回一个promise   我们可以使用then 进行链式编程
    queryData().then(function(data){
      console.log(data)
    })

	#2.  async    函数处理多个异步函数
    axios.defaults.baseURL = 'http://localhost:3000';

    async function queryData() {
      # 2.1  添加await之后 当前的await 返回结果之后才会执行后面的代码  ,get返回promise对象 
      
      var info = await axios.get('/async1');
      #2.2  让异步代码看起来、表现起来更像同步代码
      /*后台:
      app.get('/async1',(req,res)=>{
       res.send('hello')
      })
      app.get('/async1',(req,res)=>{
         if(req.query.info=='hello'){
                 res.send('world');
          }else{
               res.send(hello axios!)
          }
        })
      */
      var ret = await axios.get('async2?info=' + info.data);
      return ret.data;
    }

    queryData().then(function(data){
      console.log(data)
    })

在这里插入图片描述

2.4.2 DOM用法

(1)第一种写法

<body>

  <button id="btnPost">发起POST请求</button>
  <button id="btnGet">发起GET请求</button>

  <script src="./lib/axios.js"></script>
  <script>
    document.querySelector('#btnPost').addEventListener('click', async function () {
      // 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
      // await 只能用在被 async “修饰”的方法中
      const { data } = await axios({
        method: 'POST',
        url: 'http://www.liulongbin.top:3006/api/post',
        data: {
          name: 'zs',
          age: 20
        }
      })

      console.log(data)
    })

    document.querySelector('#btnGet').addEventListener('click', async function () {
      // 解构赋值的时候,使用 : 进行重命名
      // 1. 调用 axios 之后,使用 async/await 进行简化
      // 2. 使用解构赋值,从 axios 封装的大对象中,把 data 属性解构出来
      // 3. 把解构出来的 data 属性,使用 冒号 进行重命名,一般都重命名为 { data: res }
      const { data: res } = await axios({
        method: 'GET',
        url: 'http://www.liulongbin.top:3006/api/getbooks'
      })

      console.log(res.data)
    })

    // $.ajax()   $.get()  $.post()
    // axios()    axios.get()    axios.post()    axios.delete()   axios.put()
  </script>
</body>

(2)第二种写法

<body>
  <button id="btnGET">GET</button>
  <button id="btnPOST">POST</button>

  <script src="./lib/axios.js"></script>
  <script>
    document.querySelector('#btnGET').addEventListener('click', async function () {
      /* axios.get('url地址', {
        // GET 参数
        params: {}
      }) */

      const { data: res } = await axios.get('http://www.liulongbin.top:3006/api/getbooks', {
        params: { id: 1 }
      })
      console.log(res)
    })

    document.querySelector('#btnPOST').addEventListener('click', async function () {
      // axios.post('url', { /* POST 请求体数据 */ })
      const { data: res } = await axios.post('http://www.liulongbin.top:3006/api/post', { name: 'zs', gender: '女' })
      console.log(res)
    })
  </script>
</body>

2.5 axios的封装–项目el-admin

  1. 一般情况,axios的封装我们一般会在src文件夹下创建utils文件夹下的的request.js文件中
    在这里插入图片描述
    2.在request.js文件中引入axios,进行封装,baseURL代表后端即服务器的地址,timeout表示接口的响应时间,超时退出
  • 在页面登录的时候我们通常情况下会随机生产token,为保障服务器接口的安全性,会要求在进行axios的封装时携带token调用每个接口
  • 创建拦截器,确保能正确的接收接口返回的值
import axios from "axios";
import Element from 'element-ui'
import { getToken } from "@/utils/auth";
import * as Config from "@/settings";

let request = axios.create({
    baseURL: '/',
    timeout: Config.timeout // 请求超时时间
})

//请求拦截
request.interceptors.request.use(config => {
        if (getToken()) {
            config.headers['Authorization'] = getToken()
        }
        return config
    },
    error => {
        return Promise.reject(error)
    })

//添加响应拦截器
request.interceptors.response.use(response => {
        return response.data
    },
    error => {
        let code = error.response.data.status
        Element.Message.error(code + ' ' + error.response.data.message)
        if (code === 401) { //如果认证失败,则实行注销操作
            logout()
        }
        return Promise.reject(error)
    })

export default request

其中引用的auth.js

import Cookies from 'js-cookie'
import Config from '@/settings'

const TokenKey = Config.TokenKey

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token, rememberMe) {
  if (rememberMe) {
    return Cookies.set(TokenKey, token, { expires: Config.tokenCookieExpires })
  } else return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

setting.js

module.exports = {
  /**
   * @description 网站标题
   */
  title: 'EL-ADMIN',
  /**
   * @description 是否显示 tagsView
   */
  tagsView: true,
  /**
   * @description 固定头部
   */
  fixedHeader: true,
  /**
   * @description 记住密码状态下的token在Cookie中存储的天数,默认1天
   */
  tokenCookieExpires: 1,
  /**
   * @description 记住密码状态下的密码在Cookie中存储的天数,默认1天s
   */
  passCookieExpires: 1,
  /**
   * @description 是否只保持一个子菜单的展开
   */
  uniqueOpened: true,
  /**
   * @description token key
   */
  TokenKey: 'EL-ADMIN-TOEKN',
  /**
   * @description 请求超时时间,毫秒(默认2分钟)
   */
  timeout: 1200000,
  /**
   * @description 是否显示logo
   */
  sidebarLogo: true,
  /**
   * 是否显示设置的底部信息
   */
  showFooter: true,
  /**
   * 底部文字,支持html语法
   */
  footerTxt: '© 2019 Zheng Jie <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a>',
  /**
   * 备案号
   */
  caseNumber: '浙ICP备18005431号'
}

  1. .创建api文件夹 ,在api文件夹下创建接口文件dept.js,文件中引入src中的request.js文件,创建接口函数,区分get方法和post方法所传入参数的不同
import request from '@/utils/request'

export function getDepts(params) {
    return request({
        url: 'api/dept',
        method: 'get',
        params
    })
}

export function getDeptSuperior(ids) {
    const data = ids.length || ids.length === 0 ? ids : Array.of(ids)
    return request({
        url: 'api/dept/superior',
        method: 'post',
        data
    })
}
  1. 在子页面中引入你所需要的接口。
  • import时,加{}和不加{}的区别:
    大括号的加与不加取决于import来源的js文件。
    如果来源js中export时明确指定export组件的名称,那么加大括号并且大括号中指定引用组件的名称,
    如果来源js是默认输出,那么引用时不用大括号,且名称随意
import {getDepts, getDeptSuperior} from "@/api/dept";
//在methods中调用接口
methods:{
   getDepts('参数').then(res=>{
     //接收后台返回的数据
      console.log(res)
  })
}

3 vue使用axios的三种方式

首先 npm i axios, npm 下载 axios 插件.

3.1 直接使用

直接在 vue 组件中导入 axios, 并直接引用.

注意一点, axios 是一个基于 promise 网络请求库, 这意味着, 你必须使用 ES6 的 then() 或者 ES8 的 async/await 来处理 Promise 实例对象. (各位, 我这里用的是 async/await.)

components/Hello.vue:
// 导入 axios
import axios from 'axios';
// 方法
methods: {
        // async/await 
        async initCartList() {
            // 解构赋值          // 发起 axios 请求
            const { data:res } = await axios({
                method: 'GET',
                url: 'https://www.xxxx.cn/api/cart',
            });
            // console.log(res);
            if (res.status === 200) return  this.data = res.list;
        },
}

3.2 main.js 配置全局 axios

main.js 文件:
// 导入 axios
import axios from 'axios' 

// 全局配置 axios 请求的根路径, 可以不写.
axios.defaults.baseURL = 'http://www.xxxx.top:8080' 
// 把 axios 挂载到 Vue 原型上. 今后,在每个 .vue 组件中发起请求,直接调用 this.$http 即可.
Vue.prototype.$http = axios 

在 Hello.vue 组件中使用:

  // 方法
  methods: {
    // 发起 axios get request
    async getInfo() {
      // 解构赋值
      const { data: res } = await this.$http({
        method: 'GET',
        url: '/api/getbooks'
      })
      console.log(res)
    }
  },

3.3 项目常用,封装写法

把 axios 请求分成了三个文件, 分别有各自的配置

  1. 首先, 新建 scr/utils/request.js 文件
// 导入 axios
import axios from 'axios'

// 调用 axios.create() 函数, 创建一个 axios 的实例对象, 用 request 来接收.
const request = axios.create({
  baseURL: 'http://www.xxxx.top:8000' // 指定请求的根路径
})

export default request
  1. 新建 src\api\articleAPI.js 文件
    这里是获取频道下的文章列表的例子, 你也可以再在 api 文件下新建一个新的接口文件
// 导入 axios 实例对象
import request from '@/utils/request.js'

// 封装获取频道下的文章列表函数
export const articleList = function(id, timestamp) {
  return request.get('/v1_0/articles', {
    params: {
      channel_id: id,
      timestamp: timestamp
    }
  })
}
  1. 在 Hello.vue 按需导入需要的接口.
// 按需导入获取文章列表数据的 API
import { articleList } from '@/api/articleAPI.js' 

// 方法
methods: {
    // 调用获取频道下的文章列表 API
    async initArticleList() {
      const { data: res } = await articleList(参数 id, 参数 timestamp)
      this.list = res.data.results
      console.log(this.list)
    },
}

4 项目中的注意点

4.1 axios请求params&data

参数传递一般有两种,一种是 使用 params, 另一种是 data的方式.
get请求

axios({
    method: 'GET',
    url: 'xxxxx',
    params: param,
  })
或者 
axios({
    method: 'GET',
    url: '/xxx?message=' + msg,
  })
或者封装的形式
export function getData(param) {
    return request({
        method: "get",
        url: "xxx",
        params: param
    })
}

post请求:

axios({
    method: 'POST',
    url: '/xxxxx',
    data: param,
  })
  或者
 axios({
    method: 'POST',
    url: '/xxxxx',
    params: param,
  })
  或者
  export function addData(data) {
    return request({
        url: "/xxx/xxx",
        method: "post",
        data
    })
}

那再实际应用中,应该怎么区分请求?

  1. data 一般对应 post请求,添加到请求体(body)中
    当axios中的请求方式为‘post’的时候,axios的数据应该是 data:{},并且默认请求的是json字符串。
    使用data传递的是一个对象,在控制台中看到的话是 request payload,一般应用在添加时,例如:登录、新增。。。

  2. params 一般对应 get请求,参数会拼接到url路径中
    当请求方式是‘get’的时候,里面的数据应该是params:{},并且默认请求的是查询字符串。
    get 请求不管使用哪种方式,最后的参数都会放到路径上。 使用param 只是axios帮你把这个参数进行了序列化,并且拼接在 url上面。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐