05 . Vue前端交互,fetch,axios,以asyncawait方式调用接口使用及案例

目标

/*
		1. 说出什么是前后端交互模式
		2. 说出Promise的相关概念和用法
		3. 使用fetch进行接口调用
		4. 使用axios进行接口调用
		5. 使用asynnc/await方式调用接口
		6. 基于后台接口实现案例
*/

前后端交互模式

接口调用方式
/*
		原生ajax
		基于jQuery的ajax
		fetch
		axios
*/
传统形式的URL
/*
		格式: schema://host:port/path?query#fragment
		
				1. schema: 协议. 例如http,https,ftp等
				2. host:  域名或者IP地址
				3. port:  端口,http默认端口80,可以省略
				4. path:  路径,例如/abc/a/b/c
				5. query:  查询参数uname=list&age=12
				6. fragment: 锚点(哈希Hash),用于定位页面某个位置
*/
Restful形式的URL
/*
			HTTP请求方式
					1. GET		查询
					2. POST		添加
					3. PUT		修改
					4. DELETE 删除
*/

Promise

传统js异步调用

异步调用分析

/*
		1. 定时任务
		2. Ajax
		3. 事件函数
*/

多次异步调用的依赖分析

/*
		多次异步调用的结果顺序不确定
		异步调用结果如果存在依赖需要嵌套
*/

Example(传统ajax)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
<div id="app">

</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div>前后端交互</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
    /*
        前后端交互,异步编程与Promise概述
     */

    var ret = '---'

    $.ajax({
        url: 'http://localhost:3000/data',
        success: function (data) {
            ret = data
            console.log(ret)
        }
    });
    console.log(ret)
</script>

</body>
</html>
Promise概述

Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从他可以获取异步操作的信息.

Promise好处
/*
		使用Promise主要有以下好处:
			可以避免多层异步调用嵌套问题(回调地狱)
			Promise对象提供了简介的API,使得控制异步操作更加容易
*/
Promise使用
/*
		基本用法
    	实例化Promise对象,构造函数中传递函数,该函数用于处理异步任务.
    	resolv和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果.
*/

var p = new Promise(function(resolve,reject){
  // 成功时调用 resolve()
  // 失败时调用 reject()
  p.then(function(ret){
    	// 从resolve得到正常结果
  },function(ret){
      // 从reject得到错误信息
  });
});

Example1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
<div id="app">

</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div>前后端交互</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
    /*
        Promise基本使用
     */
    var p = new Promise(function (resolve, reject) {
        // 这里用于实现异步任务
        setTimeout(function () {
            var flag = false;
            if (flag) {
                // 正常情况
                resolve('hello');
            } else {
                // 异常情况
                reject('500');
            }
        }, 100);
    });
    p.then(function (data) {
        console.log(data)
    }, function (info) {
        console.log(info)
    })

</script>

</body>
</html>
处理原生Ajax
function queryData(){
	return new Promise(function(resolve,reject){
		var xhr - new XMLHttpRequest();
		xhr.cnreadystatechange = function(){
			if(xhr.readyState != 4) return;
			if(xhr.status == 200){
				resolve(xhr.responseText)
			}else{
				reject('出错了');
				}
			}
			xhr.open('get','/data');
			xhr.send(null);
			})
}

处理多次Ajax请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
<div id="app">

</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div>前后端交互</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
    /*
        基于Promise发送Ajax请求
     */
    function queryData(url) {
        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) {
                    // 处理正常情况
                    resolve(xhr.responseText);
                } else {
                    // 处理异常情况
                    reject('服务器错误');
                }
            };
            xhr.open('get', url);
            xhr.send(null);
        });
        return p;
    }

    // queryData('http://localhost:3000/data')
    //     .then(function(data){
    //         console.log(data)
    //     },function(info){
    //         console.log(info)
    //     });

    // 发送多个Ajax请求并且保证顺序
    queryData('http://localhost:3000/data')
        .then(function (data) {
            console.log(data)
            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>

</body>
</html>
then参数中的函数返回值
/*
		1. 返回Promise实例对象
				返回的该实例对象会调用下一个then
				
		2. 返回普通值
				返回的普通值会直接传递给下一个then,通过then参数中函数的参数接受该值
*/

Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  
  <script type="text/javascript">
    /*
      then参数中的函数返回值
    */
    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);
      });
    }
    queryData('http://localhost:3000/data')
      .then(function(data){
        return queryData('http://localhost:3000/data1');
      })
      .then(function(data){
        return new Promise(function(resolve, reject){
          setTimeout(function(){
            resolve(123);
          },1000)
        });
      })
      .then(function(data){
        return 'hello';
      })
      .then(function(data){
        console.log(data)
      })

  </script>
</body>
</html>
Promise常用API
/*
		实例方法
			p.then() 得到异步任务的正确结果
			p.catch() 获取异常信息
			p.finally()  成功与否都会执行(尚且不是正式标准)
			
		queryData()
			.then(function(data){
				console.log(data);
			})
			
			.catch(function(data){
				console.log(data);
			})
			
			.finally(function(){
				console.log('finished');
			});
*/

Example1

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  
  <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>
</body>
</html>

对象方法

/*
		Promise.all()  并发处理多个异步任务,所有任务都执行成功才能得到结果
		Promise.race()  并发处理多个异步任务,只要有一个任务完成就能得到结果
*/

Promise.all([p1,p2,p3]).then((result) =>{
  console.log(result)
})

Promise.race([p1,p2,p3]).then((result) =>{
  console.log(result)
})

Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

<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){
    //   console.log(result)
    // })
    Promise.race([p1, p2, p3]).then(function (result) {
        console.log(result)
    })
</script>
</body>
</html>

fetch请求组件

fetch

XMLHttpRequest是一个设计粗糙的API, 配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好,兼容性不好.

基本特性
/*
		更加简单的数据获取方式,功能更强大,更灵活,可以看做是xhr升级版
		基于Promise实现
*/
基本用法

Example

fetch('/abc').then(data=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret);
})

Example1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
<div id="app">

</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script type="text/javascript">
    /*
        Fetch API基本用法
     */
    fetch('http://localhost:3000/fdata').then(function (data) {
        // text() 方法属于fetchAPI的一部分,他返回一个Promise实例对象,用于获取后台返回数据
        return data.text();
    }).then(function (data) {
        // 这里得到的才是最终的数据
        console.log(data);
    })
</script>

</body>
</html>

Example2

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title>Examples</title>
		<meta name="description" content="">
		<meta name="keywords" content="">
		<link href="" rel="stylesheet">

		<script type="text/javascript" src="lib/vue.js"></script>
	</head>
	<body>

		<div id="box">
			<button @click="handleClick()">获取影片信息</button>
			<ul>
				<li v-for="data in datalist">
					<h3>{{ data.name }}</h3>
					<img :src="data.poster">
				</li>
			</ul>
		</div>

		<script>
			new Vue({
				el: "#box",
				data: {
					datalist: []
				},
				methods: {
					handleClick() {
						fetch("./json/test.json").then(res => res.json()).then(res => {
							console.log(res.data.films)
							this.datalist = res.data.films
						})
					}
				}
			})
		</script>


		<!-- new Vue({
		el: "#box",
		data:{
			datalist:["111","222","333"]
		}
	}) -->
	</body>
</html>
fetch请求参数

常用配置选项

/*
		method(String): HTTP请求方法,默认为GET(GET,POST,PUT,DELETE)
		body(String): HTTP的请求参数
		headers(Object) HTTP的请求头,默认为{}
*/

GET请求方式的参数传递

fetch('/abc?id=123').then(data=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret)
})


fetch('/abc/123',{
	method 'get'
}).then(data=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret);
});

Example1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
<div id="app">

</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script type="text/javascript">
    /*
        Fetch API:  调用接口传递参数
     */
    // fetch('http://localhost:3000/books?id=123',{
    //     method: 'get'
    // })
    // .then(function (data) {
    //     return data.text();
    // }).then(function (data) {
    //     console.log(data)
    // });

    fetch('http://localhost:3000/books/123',{
        method: 'get'
    })
        .then(function (data) {
            return data.text();
        }).then(function (data) {
        console.log(data)
    });
</script>

</body>
</html>

POST请求方式参数传递

fetch('/books',{
	method: 'post',
	body: 'uname=list&pwd=123',
	headers: {
		'Content-Type': 'application/x-www-form-urlencoded',
}
}).then(data=>{
		return data.text();
}).then(ret=>{
		console.log(ret);
})
fetch响应结果

响应数据格式

/*
		text():  将返回体处理成字符串类型
		json():  返回结果和JSON.parse(responseText)一样
*/

fetch('/abc' then(data=>{
  // return data.text();
  return data.json();
}),then(ret=>{
  console.log(ret);
});

axios请求组件

axios基本特性
/*
		axios是一个基于Promise用于浏览器和node.js的HTTP客户端.
			具有以下特征:
					支持浏览器和node.js
					支持promise
					能拦截请求和响应
					自动转换JSON数据
*/
axios基本用法
axios.get('/adata')
	.then(ret=>{
		// data属性名称是固定的,用于获取后台响应的数据
		console.log(ret.data)
})

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    axios.get('http://localhost:3000/adata').then(function (ret) {
        // 注意data属性是固定的用法,用于获取后台的实际数据
        console.log(ret.data)
    })
</script>
</body>
</html>

Example2

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title>Examples</title>
		<meta name="description" content="">
		<meta name="keywords" content="">
		<link href="" rel="stylesheet">
		<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
		<script type="text/javascript" src="lib/vue.js"></script>
	</head>
	<body>

		<div id="box">
			<button @click="handleClick()">正在热映</button>

			<ul>
				<li v-for="data in datalist">
					<h1>{{ data.name }}</h1>
					<img :src="data.poster">
				</li>
			</ul>
		</div>

		<script>
			new Vue({
				el: "#box",
				data: {
					datalist: []
				},
				methods: {
					handleClick() {
						axios.get("./json/test.json").then(res => {
							// axios 自欧东包装data属性 res.data
							console.log(res.data.data.films)
							this.datalist = res.data.data.films
						}).catch(err => {
							console.log(err);
						})
					}
				}
			})
		</script>
	</body>
</html>
axios的常用api

GET传递参数

/*
		通过URL传递参数
		通过params选项传递参数
*/

Exmaple2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    // axios.get('http://localhost:3000/axios?id=1234').then(function (ret) {
    //     // 注意data属性是固定的用法,用于获取后台的实际数据
    //     console.log(ret.data)
    // })

    axios.get('http://localhost:3000/adata', {
        params: {
            id: 700
        }
    })
        .then(function (ret) {
            console.log(ret.data)
        })

    // axios.get('http://localhost:3000/axios/1234').then(function (ret) {
    //     // 注意data属性是固定的用法,用于获取后台的实际数据
    //     console.log(ret.data)
    // })
</script>
</body>
</html>

POST传递参数

通过选项传递参数(默认传递的是json格式的数据)

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    axios.post('http://localhost:3000/axios', {
      uname: 'lisi',
      pwd: 123
    }).then(function(ret){
      console.log(ret.data)
    })
</script>
</body>
</html>

通过URLSearchParams传递参数(application/x-www-form-urlencoded)

Example2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    var params = new URLSearchParams();
    params.append('uname','youmen');
    params.append('pwd','123');
    axios.post('http://localhost:3000/axios',params).then(function(ret) {
        console.log(ret.data)
    })
</script>
</body>
</html>
axios的响应结果
/*
		data: 实际响应回来的数据
		header: 响应头信息
		status: 响应状态码
		statusText: 响应状态信息
*/

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
        axios 响应式结果与全局配置
     */
    axios.get('http://localhost:3000/axios-json').then(function(ret) {
        console.log(ret.data)
    })
</script>
</body>
</html>
axios的全局配置
/*
		axios.default.timeout=3000; //超时时间
				axios.defaults.baseURL='http://localhost:3000/app';  // 默认地址
				
		axios.defaults.headers['mytoken'] = 'asadfjksdfjkdsaf'  // 设置请求头
*/

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
        axios 响应式结果与全局配置
     */
    axios.defaults.baseURI = 'http://localhost:3000/';
    // 设置头信息
    axios.defaults.headers['mytoken'] = 'hello';
    
    axios.get('axios-json').then(function(ret) {
        console.log(ret)
    })


</script>
</body>
</html>
axios拦截器

请求拦截器

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
        axios 拦截器
     */
    axios.interceptors.request.use(function (config) {
        console.log(config.url)
        config.headers.mytoken = 'nihao';
        return config;
    }, function (err) {
        console.log(err)
    })
    axios.get('http://localhost:3000/adata').then(function (data) {

    })
</script>
</body>
</html>
响应拦截器
// 添加一个响应拦截器
axios.interceptors.response.use(function(res){
	// 在这里对返回的数据进行处理
	return res;
},function(err){
	// 处理响应的错误信息
})

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
        axios 拦截器
     */
    axios.interceptors.response.use(function (res) {
        // console.log(res)
        var data = res.data;
        return data
        // return res;
    }, function (err) {
        console.log(err)
    })
    axios.get('http://localhost:3000/adata').then(function (data) {
        console.log(data)
    })
</script>
</body>
</html>

接口调用async/await

/*
		1.async/await是ES7引入的新语法,可以更加方便的进行异步操作.
		2.async关键字用于函数上(async函数的返回值是Prornise的实例对象)
		3.await关键字用于async函数当中(await可以得到异步结果)
*/

Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
        async/await 处理异步操作
     */
    axios.defaults.baseURL = 'http://localhost:3000';
    // axios.get('adata').then(function (ret) {
    //     console.log(ret.data)
    // })

    async function queryData() {
        var ret = await new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve('nihao')
            }, 1000);
        });
        return ret
    }
    queryData().then(function (data) {
        console.log(data)
    });
</script>
</body>
</html>
async/await处理多个异步请求
async function queryData(id){
	const info = await axios.get('/async1');
	const ret = await axios.get('async2?info='+info.data);
	retrun ret;
}

queryData.then(ret=>{
	console.log(ret)
})

Example1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    /*
      async/await处理多个异步任务
    */
    axios.defaults.baseURL = 'http://localhost:3000';

    async function queryData() {
        var info = await axios.get('async1');
        var ret = await axios.get('async2?info=' + info.data);
        return ret.data;
    }

    queryData().then(function(data){
        console.log(data)
    })
</script>
</body>
</html>

基于接口的案例

/*
    图书相关的操作基于后台接口数据进行操作
    需要调用接口的功能点
    		1. 图书列表数据加载    GET  http://localhost:3000/books
    		2. 添加图书   POST  http;//localhost:3000/books
    		3. 验证图书名称是否存在  GET http://localhost:3000/books/book/:name
    		4. 编辑图书-根据ID查询图书信息  GET http://localhost:3000/books/:id
    		5. 编辑图书-提交图书信息	PUT  http://localhost:3000/books/:id
    		6. 删除图书   DELETE http://localhost:3000/books/:id
*/

Example1

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<body>
  <div id="app">
    <div class="grid">
      <div>
        <h1>图书管理</h1>
        <div class="book">
          <div>
            <label for="id">
              编号:
            </label>
            <input type="text" id="id" v-model='id' disabled="false" v-focus>
            <label for="name">
              名称:
            </label>
            <input type="text" id="name" v-model='name'>
            <button @click='handle' :disabled="submitFlag">提交</button>
          </div>
        </div>
      </div>
      <div class="total">
        <span>图书总数:</span>
        <span>{{total}}</span>
      </div>
      <table>
        <thead>
          <tr>
            <th>编号</th>
            <th>名称</th>
            <th>时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr :key='item.id' v-for='item in books'>
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
            <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
            <td>
              <a href="" @click.prevent='toEdit(item.id)'>修改</a>
              <span>|</span>
              <a href="" @click.prevent='deleteBook(item.id)'>删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript" src="js/axios.js"></script>
  <script type="text/javascript">
    /*
      图书管理-添加图书
    */
    axios.defaults.baseURL = 'http://localhost:3000/';
    axios.interceptors.response.use(function(res){
      return res.data;
    }, function(error){
      console.log(error)
    });
    Vue.directive('focus', {
      inserted: function (el) {
        el.focus();
      }
    });
    Vue.filter('format', function(value, arg) {
      function dateFormat(date, format) {
        if (typeof date === "string") {
          var mts = date.match(/(\/Date\((\d+)\)\/)/);
          if (mts && mts.length >= 3) {
            date = parseInt(mts[2]);
          }
        }
        date = new Date(date);
        if (!date || date.toUTCString() == "Invalid Date") {
          return "";
        }
        var map = {
          "M": date.getMonth() + 1, //月份 
          "d": date.getDate(), //日 
          "h": date.getHours(), //小时 
          "m": date.getMinutes(), //分 
          "s": date.getSeconds(), //秒 
          "q": Math.floor((date.getMonth() + 3) / 3), //季度 
          "S": date.getMilliseconds() //毫秒 
        };
        format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
          var v = map[t];
          if (v !== undefined) {
            if (all.length > 1) {
              v = '0' + v;
              v = v.substr(v.length - 2);
            }
            return v;
          } else if (t === 'y') {
            return (date.getFullYear() + '').substr(4 - all.length);
          }
          return all;
        });
        return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false,
        submitFlag: false,
        id: '',
        name: '',
        books: []
      },
      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;
          }else{
            // 添加图书
            var ret = await axios.post('books', {
              name: this.name
            })
            if(ret.status == 200) {
              // 重新加载列表数据
              this.queryData();
            }
          }
          // 清空表单
          this.id = '';
          this.name = '';
        },
        toEdit: async function(id){
          // flag状态位用于区分编辑和添加操作
          this.flag = true;
          // 根据id查询出对应的图书信息
          var ret = await axios.get('books/' + id);
          this.id = ret.id;
          this.name = ret.name;
        },
        deleteBook: async function(id){
          // 删除图书
          var ret = await axios.delete('books/' + id);
          if(ret.status == 200) {
            // 重新加载列表数据
            this.queryData();
          }
        },
        queryData: async function(){
          // 调用后台接口获取图书列表数据
          // var ret = await axios.get('books');
          // this.books = ret.data;

          this.books = await axios.get('books');
        }
      },
      computed: {
        total: function(){
          // 计算图书的总数
          return this.books.length;
        }
      },
      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);
          if(ret.status == 1) {
            // 图书名称存在
            this.submitFlag = true;
          }else{
            // 图书名称不存在
            this.submitFlag = false;
          }
        }
      },
      mounted: function(){
        // var that = this;
        // axios.get('books').then(function(data){
        //   console.log(data.data)
        //   that.books = data.data;
        // })

        // axios.get('books').then((data)=>{
        //   console.log(data.data)
        //   this.books = data.data;
        // })

        this.queryData();
      }
    });
  </script>
</body>
</html>
posted @ 2020-11-19 01:54  常见-youmen  阅读(683)  评论(0编辑  收藏  举报