零基础学Vue--day04

本文是Vue学习系列的第四天,主要讲解了接口调用的不同方式,包括原生Ajax、fetch API、axios和async/await。重点讨论了Promise解决异步问题,以及如何使用axios进行接口调用。同时,还介绍了图书列表案例,涵盖了图书的加载、添加、验证、编辑和删除操作。
摘要由CSDN通过智能技术生成

1.接口调用方式

  • 原生ajax;基于 jQuery 的ajax;fetch;axios;

1)JavaScript 的执行环境是单线程;异步模式可以执行多个任务;

  • JS中常见的异步调用:定时任务;ajax;事件函数;
  • 多次异步调用的结果,顺序不确定 (先执行其他函数,再执行异步);如果存在依赖需要,嵌套;回调地狱;

2)传统形式的 URL: http://www.baidu.com/java/web?flag=1#function

  Restful 形式的 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. promise

1) promise 解决异步 深层嵌套问题(回调地狱)

//使用new构建一个 Promise实例,并传入一个函数,用于处理异步任务;函数传入两个参数:
//resolve 异步操作成功后,执行的回调函数;reject 异步操作失败后,执行的回调函数;
//并通过p.then获取处理结果;

var p = new Promise(function(resolve, reject){
   // 这里用于实现异步任务;resolve reject这两个参数,都是方法,可以调用; 
   setTimeout(function(){
        var flag = false;
        if(flag) { 
          resolve('hello'); // 成功时调用 resolve()
        }else{
          reject('出错了'); // 失败时调用 reject()
        }
   }, 100);
});    
//用then方法指定 resolved状态和 reject状态的回调函数   
p.then(function(data){  
  //从resolve得到,成功时的处理结果 (then里的this不是vue实例,要用箭头函数)
},function(info){
  //从reject得到,失败时的处理结果
});

2) Promise 发送多次Ajax请求 并保证顺序

//return一个新的,Promise实例对象,下一个then的调用者,
//就是上面 return出来的 Promise实例对象;data接受上一个异步任务,的处理结果;
queryData('http://localhost:3000/data') //queryData()相当于p
  .then(function(data){
    console.log(data)
    return queryData('http://localhost:3000/data1');//返回值,是一个新的 Promise实例对象
  })     
  .then(function(data){//得到新Promise()异步任务的结果;
    console.log(data);
    return queryData('http://localhost:3000/data2');
  })
  .then(function(data){
    console.log(data)
  });

3) then参数中,函数的返回值:

1、返回 Promise实例对象:
返回的该实例对象,会调用下一个then;在下一个then中,得到上一个,异步任务的处理结果;
2、返回普通值:
会直接传递给下一个then;会产生一个新的,默认的 Promise实例对象,调用下一个then;
4) console.dir(Promise)
在这里插入图片描述
1. Promise 常用API-实例方法 (位于Promise原型中的方法,通过实例.对象调用)

P.then() 得到成功时,执行的正确结果;
P.catch() 获取异常信息:和then的错误方法等效,接收 reject() 传递过来的信息;
P.finally() 成功与否都会执行(尚不是正式标准):作一些提示信息,或销毁一些资源;
function foo() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            reject('error');
        }, 100);
    })
}
foo()
  .then(function(data){
     console.log(data)
   } 
  .catch(function(data){
     console.log(data) //error 接收reject传递过来的异常信息
  })
  .finally(function(){
     console.log('finished')
  });

2. Promise 常用API-对象方法 (直接通过Promise 函数名称调用;与prototype原型对象平级)
Promise.all().then() 并发处理多个异步任务,所有任务都执行完,才能得到结果;
接受一个数组,作为参数;数组中均为 promise实例对象,每一个实例对象,完成一个异步的操作;结果也是一个数组,和传参时一 一对应;
Promise.race().then() 并发处理多个异步任务,只要有一个任务完成,就能得到结果
同样接受一个数组,作为参数;把第一个改变状态的 promise的返回值,传给回调函数;只得到一个,最快返回的结果;

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) 
})
Promise.race([p1,p2,p3]).then(function(result){
  // 由于p1执行较快,Promise的then()将获得结果'P1';p2、p3仍继续执行,但执行结果将被丢弃;
  console.log(result) // HELLO TOM
})

3. 接口调用-fetch API

  • fetch 基于Promise实现;默认是get请求,返回一个 Promise实例对象;
  • fetch 就是 ajax + Promise,使用的方式和 jquery 提供的 $.ajax() 差不多;
  • fetch 不是 ajax 的进一步封装,而是原生 js,没有使用 XMLHttpRequest对象;
fetch('http://localhost:3000/fdata').then(function(data){
 //text()属于fetch API的一部分,它返回一个Promise实例对象,
 //return把它返回,通过下一个 then得到具体的数据
  return data.text(); //二进制
}).then(function(data){
  console.log(data); //这里得到的,才是最终数据
}).catch(function(info){
  console.log(info);
})

1) fetch 请求参数:在url后面,添加一个{对象},用于配置请求信息

常用配置项:
method:请求方法,默认get (delete、post、put)
body:请求参数(post、put请求用)
headers:请求头,默认为{} 
// GET参数传递 - restful形式的URL   
fetch('http://localhost:3000/books/456', {
        method: 'get'/'delete'
    })
    .then(function(data) {
        return data.text();
    }).then(function(data) {
        console.log(data)
    });
// POST请求传参 (PUT请求,要加 id/123)
fetch('http://localhost:3000/books', {
        method: 'post',
        body: JSON.stringify({ //把对象转换成json格式的字符串
            uname: '张三',
            pwd: '456'
        }),
        headers: { //json格式请求
            'Content-Type': 'application/json'
        }
    })
    .then(function(data) {
        return data.text();
    }).then(function(data) {
        console.log(data)
    });

2) fetch 响应结果的数据格式

  • 用 fetch 来获取数据,返回的是一个 response对象,其中包括一堆原始字节;需要通过调用方法,将其转换为,相应格式的数据,比如 JSON,BLOB 或者 TEXT 等等;
fetch('http://localhost:3000/json').then(function(data){
  return data.json();   //和JSON.parse(data)作用一样,将字符串,转换成json形式的对象; 
}).then(function(data){
  console.log(data) //Object age:13 uname:'lisi' gender:'male'
  console.log(data.uname) //lisi
})
-----------------------------------------------------------------------------------------
fetch('http://localhost:3000/json').then(function(data){
  return data.text();   //将返回的数据,转换成字符串;(对象内是字符串) 
}).then(function(data){
  console.log(data) //{"uname":"lisi","age":"13","gender":"male"},这是字符串,不是对象
  console.log(typeof data) //string,字符串无法通过 .的形式,得到 uname  
  var obj = JSON.parse(data); //转换成对象
  console.log(obj.uname,obj.age,obj.gender) //lisi 13 male
})
// json() 对象形式的,不用转换数据;
// text() 字符串形式的,要多一步 JSON.parse(data),转换成对象;
var obj = {
    uname: 'lisi',
    age: 12
}
for (var key in obj) {
    console.log(obj[key])
}
//obj对象中,没有 key这个属性,所以obj.key=undefined;obj[key]=lisi 12

4. 接口调用-axios

  • 基于 promise 用于浏览器和 node.js 的 http客户端;(http客户端:可以调用一个http形式的后台接口)
  • 专门的,第三方的 js库,用来实现接口的调用;(需要引入 axios.js库文件)
  • 支持浏览器和 node.js
  • 能拦截请求和响应
  • 自动转换 JSON数据
  • 能转换请求和响应数据

1) axios基础用法

axios.get('http://localhost:3000/adata')
  .then(function(ret){
     console.log(ret) //返回的是一个对象,data是其中的 一个属性;
     console.log(ret.data) //data属于axios API的一部分,用于获取后台数据;
})

2) axios 常用API

get:   查询数据 
delete:删除数据 
post:  添加数据
put:   修改数据
getdelete请求传参

#1.1 get请求-通过传统'url',以'?'的形式传参;
axios.get('http://localhost:3000/axios?id=123')
   .then(function(ret){
  	  console.log(ret.data)
   })
#1.2 get请求-通过'restful'形式的 url传参; 
axios.get('http://localhost:3000/axios/123')
   .then(function(ret){
  	  console.log(ret.data)
   })
#1.3 get请求-通过'params'形式传参;(后台接口和传统url用的接口一样)
axios.get('http://localhost:3000/axios', {
   params: {
     id: 789
   }
}).then(function(ret){
   console.log(ret.data)
})
#2 delete请求-传参形式和 get一样
axios.delete('http://localhost:3000/axios', {
  params: {
    id: 111
  }
}).then(function(ret){
   console.log(ret.data)
})
post和 put请求传参

#3.1 post请求-通过对象传参 (默认传递的是 Json格式的数据)
axios.post('http://localhost:3000/axios', {
  uname: 'lisi', 
  pwd: 123  //提交Json格式的数据: {"uname":"lisi","pwd":123},需要后台提供支持;
}).then(function(ret){
  console.log(ret.data)
})
#3.2 post请求-通过'URLSearchParams'传参 
var params = new URLSearchParams();
params.append('uname', 'lisi');
params.append('pwd', '111'); //提交表单形式的数据:字符串'uname=lisi&pwd=111'
axios.post('http://localhost:3000/axios', params)
   .then(function(ret){
   	  console.log(ret.data)
   })
//表单上传编码格式为 application/x-www-form-urlencoded (Request Headers中),参数格式为key=value&key=value
//URLSearchParams()构造函数,产生一个实例对象,把参数加到实例对象里,然后整体作为参数传递;

#4 put请求-传参形式和 post一样 (多传一个修改的id)
axios.put('http://localhost:3000/axios/123', {
  uname: 'lisi',
  pwd: 123
}).then(function(ret){
  console.log(ret.data)
})

3) axios 的响应结果

请求发出去后,后台响应对应的结果,axios把这个结果,封装成了一个对象:
data 响应回来的数据,json形式的
headers 响应头信息
status 响应状态码:200
statusTest 响应状态信息:"ok"

在这里插入图片描述
4) axios 全局配置

// 配置默认地址: 会自动拼接,简写的请求路径;
axios.defaults.baseURL = 'https://api.example.com/';
// 配置超时时间: 3000ms内不响应,请求出错;
axios.defaults.timeout = 3000;
// 配置请求头: 登录时会用到,携带token信息,登录成功;
axios.defaults.headers['Authorization'] = AUTH_TOKEN;
// 配置公共 post的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// axios.get('http://localhost:3000/json')
axios.defaults.baseURL = 'http://localhost:3000/';
axios.defaults.headers['mytoken'] = 'hello'; 
//设置完请求头后,发出请求时,会在请求头中,添加这个属性,值是后面指定的值;
axios.get('json').then(function(ret){
   console.log(ret.data.uname)
})
//对于跨域来说,请求头是需要,后台来配置的;res.header('','mytoken')允许传递'mytoken';

在这里插入图片描述
5) axios 拦截器

1.请求拦截器:在请求发送前,设置一些信息;比如:在每个请求体里,加上token;
//第一个函数:通过形参 config,来做信息的设置;config 一定要return出去,否则配置不生效;
//第二个函数:用于处理响应的,错误信息
axios.interceptors.request.use(function(config) {
  //console.log(config.url) //得到请求的 url地址,可以根据 url来判断,添加请求头;     
  config.headers.mytoken = 'nihao'; //配置请求头;与 axios.defaults.headers['mytoken']类似  
  return config;  //一定要return 
}, function(err){         
  console.log(err)  
})

2.响应拦截器:在获取数据之前,进行加工处理;
//例如:服务器返回登录状态失效,需要重新登录时,跳转到登录页
axios.interceptors.response.use(function(res) {
  //res:axios返回的包装对象,通过对象的.data,才能拿到数据
  //对返回的数据,进行处理;只要具体的数据,不要包装的对象;
  var data = res.data;
  return data; 
}, function(err){  
  console.log(err)
})
axios.get('http://localhost:3000/adata').then(function(data){
  console.log(data) //hello axios;请求头Request Headers中 mytoken:nihao
})

5. 接口调用-async/await

  • async/await ES7语法;async关键字,放到函数前面,async函数隐式返回一个 Promise实例对象;
  • await关键字,只能用于async函数中,await后面要跟一个,Promise实例对象,用于得到异步处理的结果;
//传统的 axios方式,调用接口
axios.get('http:localhost:3000/adata').then(function(ret){
   console.log(ret.data) //hello axios
})

async function queryData() {
   var ret = await axios.get('http:localhost:3000/adata');
   console.log(ret.data) //hello axios
} 
queryData()

//async函数内部,把异步结果返回出去;调用queryData(),通过.then的方式,获取上面的返回值;
async function queryData() {
   var ret = await axios.get('http:localhost:3000/adata');
   return ret.data; //把异步结果返回出去
}
queryData().then(function(data){
   console.log(data)  //hello axios           
})

// await后面要跟一个,Promise实例对象,在Promise中,处理异步任务;
async function queryData() {
  var ret = await new Promise(function(resolve, reject){
    setTimeout(function(){
      resolve('nihao')
    },1000);
  })
  return ret;
}
// 任何一个async函数,都会隐式返回一个promise;可以使用.then,进行链式编程;
queryData().then(function(data){
  console.log(data) //nihao
})
  • async/await 处理多个异步请求
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
   //当前的 await 返回结果后,才会执行后面的代码;info请求结果,作为第二个请求的参数;
   var info = await axios.get('async1');  
   var ret = await axios.get('async2?info=' + info.data); //info=info.data
   return ret.data;
}
// 后台 if(req.query.info=='hello'){res.send('world')}else{res.send('error')}
queryData().then(function(data){
   console.log(data)
})

6. 图书列表案例

在这里插入图片描述

router.js //提供了六个后台接口
service.js //具体的后台接口业务功能
data.json //模拟数据库
index.js  //入口文件
启动后台服务: 终端 nodemon -->默认执行的是index.js

1) 图书列表加载
导入axios 用来发送ajax

<div id="app">
    <table>
        <thead> ... ... </thead>
        <tbody>
            <!-- 把 books 中的数据,渲染到页面上   -->
            <tr :key='item.id' v-for='item in books'>
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.date }}</td>
                <td>
                    <a href="">修改</a>
                    <span>|</span>
                    <a href="">删除</a>
                </td>
            </tr>
        </tbody>
    </table>
</div>

<script type="text/javascript" src="js/vue.js"></script>
1.导入axios.js   
<script type="text/javascript" src="js/axios.js"></script>

<script type="text/javascript">
    # 2.配置基准路径 
    axios.defaults.baseURL = 'http://localhost:3000/';
    # 3.配置响应拦截器 data = res.data
    axios.interceptors.response.use(function(res) {
        return res.data;
    }, function(error) {
        console.log(error)
    });

    var vm = new Vue({
        el: '#app',
        data: {
            flag: false,
            submitFlag: false,
            id: '',
            name: '',
            books: []
        },
        methods: {
            # 4.获取图书列表数据
            queryData: async function() {
                // var ret = await axios.get('books');
                // this.books = ret.data;
                # 把获取的数据,放在books 里面   
                this.books = await axios.get('books');
            }
        },
        mounted: function() {
            # 5.mounted: DOM加载完毕,立即调用函数
            // var that = this;  
            // axios.get('books').then(function(data){
            //   that.books = data.data;
            // }) 

            //.then 里的 this,不是vue实例,要用箭头函数
            // axios.get('books').then((data)=>{
            //   this.books = data.data;
            // })
            
            this.queryData();
        }
    });
</script>

2) 添加图书

methods: {
   handle: async function(){
      if(this.flag) {
        // 编辑图书:根据当前的ID,更新数组中对应的数据
        this.books.some((item) => {
          if(item.id == this.id) {
            item.name = this.name;            
            return true; //完成更新操作后,终止循环
          }
        });
        this.flag = false;
      }else{
        # 获取用户输入的数据,发送添加图书 ajax请求  
        var ret = await axios.post('books', {
          name: this.name
        })
        # 根据返回的状态码,判断是否成功;成功,重新加载列表数据
        if(ret.status == 200) {             
           this.queryData(); //渲染最新的数据 
        }
      }
      // 清空表单
      this.id = '';
      this.name = '';
    }        
 }         

3) 验证图书名称是否存在

watch: {
   name: async function(val) {
      // 验证图书名称是否已经存在
      // var flag = this.books.some(function(item){
      //   return item.name == val;
      // });
      var ret = await axios.get('/books/book/' + this.name); //this.name也可以是val
      if(ret.status == 1) {
        // 图书名称存在,禁用 "提交" 按钮
        this.submitFlag = true;
      }else{
        // 图书名称不存在,可以提交
        this.submitFlag = false;
      }
   }
}

4) 编辑图书
根据状态位,判断是添加,还是编辑;

methods: {
   handle: async function(){
      if(this.flag) {
        # 把用户输入的信息,提交到后台
        var ret = await axios.put('books/' + this.id, {
          name: this.name
        });
        if(ret.status == 200){
          # 添加成功,重新加载数据
          this.queryData();
        }
        this.flag = false; # 修改完,flag状态位,重新设为false
      }else{
        // 添加图书
        var ret = await axios.post('books', {
          name: this.name
        })
        if(ret.status == 200) {
          // 重新加载列表数据
          this.queryData();
        }
      }
      // 清空表单
      this.id = '';
      this.name = '';
   },
   toEdit: async function(id){
      # input框已经禁用;flag状态位,默认为false,添加操作;为true时,编辑操作;
      this.flag = true;
      # 根据id,发送ajax;加载出,要编辑图书的,最新信息
      var ret = await axios.get('books/' + id);
      this.id = ret.id;
      this.name = ret.name;
   }
}

5) 删除图书

deleteBook: async function(id){
   // 把需要删除的书籍id,传给后台
   var ret = await axios.delete('books/' + id);
   if(ret.status == 200) {
      // 重新加载列表数据
      this.queryData();
   }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值