【Vue】Vue全家桶(五)前后端交互+接口调用方法(fetch、axios、async/await)
【Vue】Vue全家桶(五)前后端交互+接口调用方法(fetch、axios、async/await)
文章目录
1. 前后端交互模式
前后端交互
:前端页面通过工具调用后端接口,拿到数据库中的数据,然后在做前端页面的渲染。
什么是前端? 什么是后端? 什么是数据库?
1.1 前端调用后端接口的方式
- 原生ajax
- 基于jQuery的ajax
- fetch
- axios
1.2 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=120
- 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. Promise用法
2.1 异步调用
-
异步场景
① 定时任务
② Ajax
③ 事件函数
-
多次异步调用的依赖分析
多次异步调用的结果顺序不确定, 异步调用结果如果存在依赖需要嵌套,嵌套太多会形成回调地狱回调地狱
:一个异步请求套着一个异步请求,一个异步请求依赖于另一个的执行结果,使用回调的方式相互嵌套,代码可读性低、编写费劲、不方便后期维护
2.2 Promise概述
Promise
:ES6引入的异步编程的新解决方案,语法是一个构造函数
,用来封装异步操作并可以获取其成功或失败的结果. resolve
和reject
两个参数用于处理成功和失败两种情况,并通过p.then
获取处理结果
Promise 中的异步体现在then
和catch
中,所以写在 Promise 中的代码是被当做同步任务立即执行的。
//手写一个promise模板
var promise = new Promise((resolve,reject) => {
if (操作成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (error) {
// failure
})
Promise对象有三种状态:初始化pending 成功fulfilled 失败rejected
- Promise 就是一个对象,用来表示并传递异步操作的最终结果
- Promise {: PromiseResult} PromiseState:状态 PromiseResult:返回值
- Promise 最主要的交互方式:将回调函数传入 then 方法来获得最终结果或出错原因
- Promise 代码书写上的表现:以“链式调用”代替回调函数层层嵌套(回调地狱)p.then().then()
使用Promise主要有以下好处
:
- 可以避免多层异步调用嵌套问题(回调地狱)
- Promise对象提供了简洁的API,使得控制异步操作更加容易
//02-Promise基本使用.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type='text/javascript'>
var p = new Promise( (resolve, reject) =>{
//这里用于实现异步任务
setTimeout(function () {
var flag = true;
if (flag) {
//正常情况
resolve('hello')
} else {
//异常情况
reject('出错了')
}
}, 1000)
});
p.then(function (value) {
console.log(value);
},
function (error) {
console.log(error);
})
</script>
</body>
</html>
2.3 基于Promise处理Ajax请求
1.Promise封装原生Ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function queryData(url) {
return new Promise( (resolve, reject) =>{
//原生请求
//1.创建Ajax对象
const xhr = new XMLHttpRequest();
//2.初始化
xhr.open('get', url);
//3.发送请求
xhr.send()
//4.绑定事件,处理响应结果
xhr.onreadystatechange = function () {
//判断状态
if (xhr.readyState == 4) {
//判断响应状态码200-299
if (xhr.status >= 200 && xhr.status <= 299) {
//成功
resolve(xhr.response)
} else {
//失败
reject(xhr.status)
}
}
}
})
};
queryData('http://localhost:3000/data')
.then(function (value) {
console.log(value);
}).then(function (error) {
console.log(error);
})
</script>
</body>
</html>
//index.js
//引入express框架
const express = require('express')
//创建网站服务器
const app = express()
//引入接收post请求参数第三方包 `body-parser`。
const bodyParser = require('body-parser')
// 处理静态资源
//app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。
app.use(express.static('public'))
// 处理参数
app.use(bodyParser.json());
// 配置body-parser模块
app.use(bodyParser.urlencoded({
extended: false
}));
// 设置允许跨域访问该服务
app.all('*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Headers', 'mytoken');
next();
});
// 路由
//中间件示例
//app.get('请求路径', '处理函数') // 接收并处理get请求
//当客户端以get方式访问/data路由
app.get('/data', (req, res) => {
//对客户端做出响应
res.send('Hello World!')
})
app.get('/data1', (req, res) => {
setTimeout(function () {
res.send('Hello TOM!')
}, 1000);
})
app.get('/data2', (req, res) => {
res.send('Hello JERRY!')
})
// 启动监听
app.listen(3000, () => {
console.log('服务器启动成功')
})
2.发送多个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)
});
2.4 then参数中的函数返回值
1.返回Promise实例对象
返回的该实例对象会调用下一个then,得到上一步的处理结果
2.返回普通值
返回的普通值会直接传递给下一个then,通过then参数中函数的参数接收该值
queryData('http://localhost:3000/data')
.then(function(data){
return queryData('http://localhost:3000/data1');
})
.then(function(data){
//返回Promise实例对象
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(123);
},1000)
});
})
// 返回的该实例对象会调用下一个then
.then(function(data){
console.log(data)//123
})
queryData('http://localhost:3000/data')
.then(function(data){
return queryData('http://localhost:3000/data1');
})
//返回普通值
.then(function(data){
return 'hello';
})
//回的普通值会直接传递给下一个then,通过then参数中函数的参数接收该值
.then(function(data){
console.log(data)//hello
})
2.5 Promise常用的API
1.实例方法
- p.then()得到异步任务的正确结果
- p.catch()获取异常信息
- p.finally()成功与否都会执行
//p.then()得到异步任务的正确结果
.then(function(data){
console.log(data)
})
//p.catch()获取异常信息
.catch(function(data){
console.log(data)
})
//p.finally()成功与否都会执行
.finally(function(){
console.log('finished')
});
2.对象方法
- Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果
- Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.all([p1, p2, p3]).then(function (result) {
console.log(result)
})
Promise.race([p1, p2, p3]).then(function (result) {
console.log(result)
})
3. 接口调用-fetch用法
3.1 fetch概述
1.基本特性
- 更加简单的数据获取方式,功能更强大、更灵活,可以看做是
ajax的升级版
- 基于Promise实现
2.语法结构
//通过fetchAPI调用接口,通过then获取数据
fetch(url).then(fn2)
.then(fn3)
...
.catch(fn)
3.2 fetch的基本用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script type="text/javascript">
fetch("http://localhost:3000/fdata")
.then(function (data) {
// text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
return data.text();
})
.then(function (data) {
console.log(data);
});
</script>
</body>
</html>
//路由
app.get('/fdata', (req, res) => {
res.send('Hello Fetch!')
})
3.3 fetch请求参数
1.常用配置选项
- method(String):HTTP请求方法,默认为GET(GET,POST,PUT,DELETE增删改查)
- body(String):HTTP的请求参数
- headers(Object):HTTP的请求头,默认为{ }
fetch('/abc",{
method:'get'
}).then(data=>(
return data.text();
1).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
};
2.GET请求方式的参数传递
// GET参数传递-传统URL
fetch('http://localhost:3000/books?id=123', {
//默认为get可以不添加
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
// GET参数传递-restful形式的URL 通过/传递参数
fetch('http://localhost:3000/books/456', {
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
//路由
app.get('/books', (req, res) => {
//req.query获取get 请求方式
res.send('传统的URL传递参数!' + req.query.id)
})
//id为占位符,表示当前路由要接受一个id作为参数
//req.param适用于restful风格url中的参数的解析
app.get('/books/:id', (req, res) => {
res.send('Restful形式的URL传递参数!' + req.params.id)
})
3.DELETE请求方式的参数传递
// DELETE请求方式参数传递
fetch('http://localhost:3000/books/789', {
method: 'delete'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
//路由
app.delete('/books/:id', (req, res) => {
res.send('DELETE请求传递参数!' + req.params.id)
})
4.POST请求方式的参数传递
// POST请求传参
fetch('http://localhost:3000/books', {
method: 'post',
body: 'uname=lisi&pwd=123',
headers: {
//传统格式数据
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
// POST请求传参
fetch('http://localhost:3000/books', {
method: 'post',
//转换为JSON字符串
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {
//json格式数据
'Content-Type': 'application/json'
}
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
//路由
app.post('/books', (req, res) => {
res.send('POST请求传递参数!' + req.body.uname + '---' + req.body.pwd)
})
5.PUT请求方式的参数传递
//PUT请求传参 一般用于修改数据 /123为需要修改的数据
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)
});
//路由
app.put('/books/:id', (req, res) => {
res.send('PUT请求传递参数!' + req.params.id + '---' + req.body.uname + '---' + req.body.pwd)
})
3.4 fetch响应结果
响应数据格式
- text():将返回体处理成字符串类型
- json():返回结果和JSON.parse(responseText)一样 对象类型
fetch('/abc' then(data=>{
//return data text();
return data.json();
}).then(data=>{
console.log(data)
})
4. 接口调用-axios用法
4.1 axios概述
axios
是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中(专用用于调用后台接口的库)
它具有以下特征:
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 自动转换JSON数据
4.2 axios的基本用法
axios.get('http://localhost:3000/adata')
.then(function(ret){
// 注意data属性是固定的用法,用于获取后台的实际数据
// console.log(ret.data)
console.log(ret)
})
//路由
app.get('/adata', (req, res) => {
res.send('Hello axios!')
})
4.3 axios的常用API
- get:查询数据
- post:添加数据
- put:修改数据
- delete:删除数据
1.GET参数
- 通过URL传递参数
- 通过params选项传递参数
// axios get请求传参
//通过URL传递参数
//下面两种都可以
axios.get('http://localhost:3000/axios?id=123')
.then(function(ret){
console.log(ret.data)
})
axios.get('http://localhost:3000/axios/123')
.then(function(ret){
console.log(ret.data)
})
//通过params选项传递参数
axios.get('http://localhost:3000/axios', {
params: {
id: 789
}
}).then(function(ret){
console.log(ret.data)
})
//路由
app.get('/axios', (req, res) => {
res.send('axios get 传递参数' + req.query.id)
})
app.get('/axios/:id', (req, res) => {
res.send('axios get (Restful) 传递参数' + req.params.id)
})
2.DELETE参数
- 参数传递方式与GET类似
3.POST参数
- 通过选项传递参数(默认传递的是json格式的数据)
- 通过URLSearchParams传递参数(application/x-www-form-urlencoded)
JSON样例:首先一个花括号{ },整个代表一个对象,同时里面是一种Key-Value的存储形式,它还有不同的数据类型来区分
//通过选项传递参数
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
//通过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)
})
//路由
app.post('/axios', (req, res) => {
res.send('axios post 传递参数' + req.body.uname + '---' + req.body.pwd)
})
4.PUT传递参数
- 参数传递方式与POST类似
4.4 axios的响应结果
响应结果的主要属性
- data:实际响应回来的数据
- headers:响应头信息
- status:响应状态码
- statusText:响应状态信息
4.5 axios全局配置
- axios.defaults.timeout = 3000;//超时时间
- axios.defaults.baseURL='http://localhost:3000;//默认地址
- axios.defaults.headers[‘mytoken’] = ‘hello’; //设置请求头
// 配置请求的基准URL地址
axios.defaults.baseURL = 'http://localhost:3000/';
// 配置请求头信息
axios.defaults.headers['mytoken'] = 'hello';
axios.get('axios-json')
.then(function(ret){
console.log(ret.data.uname)
})
//路由
app.get('/axios-json', (req, res) => {
res.json({
uname: 'lisi',
age: 12
});
})
4.6 aixos拦截器
1.请求拦截器
在请求发出之前设置一些信息
//添加一个请求拦截器
axios.interceptors.request.use(function(config) {
//在请求发出之前进行一些信息设置
return config;
}, function(err){
//处理响应的错误信息
console.log(err)
})
2.响应拦截器
在获取数据之前对数据做一些加工处理
//添加一个响应拦截器
axios.interceptors.response.use(function(res) {
//在这里对返回的数据进行处理
return res;
}, function(err){
//处理响应的错误信息
console.log(err)
})
//请求拦截器
axios.interceptors.request.use(function(config) {
console.log(config.url)
config.headers.mytoken = 'nihao';
return config;
}, function(err){
console.log(err)
})
//响应拦截器
axios.interceptors.response.use(function(res) {
// console.log(res)
var data = res.data;
return data;
}, function(err){
console.log(err)
})
axios.get('http://localhost:3000/adata')
.then(function(data){
console.log(data)
})
//路由
app.get('/adata', (req, res) => {
res.send('Hello axios!')
})
5. 接口调用-async和await用法
async
和await
两种语法结合可以让异步代码看起来像同步代码一样,简化异步函数的写法
async函数
:
1.async函数的返回值为promise对象;
2.promise对象的结果由async函数执行的返回值决定
3.async 是Generator函数的语法糖,并对Generator函数进行了改进,是对 yield 的简单封装
async function fn() {
//1.如果返回结果是 非promise对象,状态为成功,返回值为对象成功值fulfilled
return 123;
//2.抛出错误
throw "出错啦";
}
const result = fn();
console.log(result); // Promise {<fulfilled>: 123} Promise {<rejected>: '出错啦'}
-----------------------------------------------------------------------------------------
async function fn() {
//3.如果返回的promise对象,那么返回的最终结果就是Promise对象
return new Promise((reslove, reject) => {
//resolve('成功');
reject('失败');
})
}
const result = fn();
console.log(result); //Promise {<rejected>: '失败'}
// then方法来获得最终结果或出错原因
result.then(
(value) => {
console.log(value);
},
(reason) => {
console.log(reason); //失败
}
)
await表达式
:
1.await必须写在aysnc函数中;
2.await后面的表达式一般为Promise对象;
3.await返回的是Promise成功的值;
4.await的Promise失败了,就会抛出异常,无法处理promise返回的reject对象,需要通过try…catch捕获处理.
//async函数 + await表达式:异步函数
async function fn() {
//await 返回的promise成功值
let result = await new Promise((resolve, reject) => {
resolve('成功')
});
console.log(result); //成功
}
fn();
5.1 async/await的基本用法
- async/await是ES7引入的新语法,可以更加方便的进行异步操作
- async关键字用于函数上(async函数的返回值是Promise实例对象)
- await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(id){
const ret =await axios.get('/data');
return ret;
}
queryData.then(ret=>{
console.log(ret)
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="js/axios.js"></script>
<script type="text/javascript">
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);//nihao
});
</script>
</body>
</html>
5.2 async/await处理多个异步请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="js/axios.js"></script>
<script type="text/javascript">
// 配置请求的基准URL地址
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>
//路由
app.get('/async1', (req, res) => {
res.send('hello1')
})
app.get('/async2', (req, res) => {
if (req.query.info == 'hello') {
res.send('world')
} else {
res.send('error')
}
})
6. 基于后台接口重构图书管理案例
- 图书相关的操作基于后台接口数据进行操作
- 需要调用接口的功能点
① 图书列表数据加载 GET http://localhost:3000/books
② 添加图书 POST http://localhost:3000/books
③ 验证图书名称是否存在 GET http://localhost:3000/books/book/name
④ 编辑图书-根据ID查询图书信息 GET http://localhost:3000/books/:id
⑤ 编辑图书-提交图书信息 PUT http://localhost:3000/books/:id
⑥ 删除图书 DELETE http://localhost:3000/books/id
图书管理后台接口文档
基准路径: http://localhost:3000/
获取图书列表数据
- 路径:books
- 请求参数:无
- 响应结果
[{
"id": "4",
"name": "红楼梦",
"date": 2525609975000
}, {
"name": "三国演义",
"date": 2525609975000,
"id": 5
}, {
"name": "水浒传",
"date": 2525609975000,
"id": 6
}, {
"name": "西游记",
"date": 2525609975000,
"id": 7
}]
添加图书-提交图书信息
- 路径:books
- 请求参数
- name : 图书名称
- 响应结果
{
"status": 200 // (200表示成功;500表示失败)
}
编辑图书-根据ID查询图书信息
- 路径:books/:id
- 请求参数:无
- 响应结果
{
"name":"西游记",
"date":2525609975000,
"id":7
}
编辑图书-提交图书信息
- 路径:books/:id
- 请求参数
- name : 图书名称
- 响应结果
{
"status": 200 // (200表示成功;500表示失败)
}
删除图书信息
- 路径:books/:id
- 请求参数: 无
- 响应结果
{
"status": 200 // (200表示成功;500表示失败)
}
验证图书名称是否存在
- 路径:books/book/:name
- 请求参数:无
- 响应结果
{
"status": 1 // (1表示存在;2表示不存在)
}
{
"status": 1 // (1表示存在;2表示不存在)
}
//引入express框架
const express = require('express');
//引入路径处理模块
const path = require('path');
//引入路由
const router = require('./router.js');
//引入post参数处理模块
const bodyParser = require('body-parser');
//创建网站服务器
const app = express();
// 启动静态资源服务
app.use(express.static('public'));
// 处理请求参数
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// 为路由对象匹配请求路径
app.use(router);
// 监听端口
app.listen(3000,()=>{
console.log('服务器启动成功');
});
/*路由模块*/
const express = require('express');
//创建路由对象
const router = express.Router();
const service = require('./service.js');
// 查询图书列表
router.get('/books',service.getAllBooks);
// 添加图书(提交表单)
router.post('/books',service.addBook);
// 跳转到编辑图书信息页面
router.get('/books/:id',service.toEditBook);
// router.get('/toEditBook',service.toEditBook);
// 编辑图书提交表单
router.put('/books/:id',service.editBook);
// 删除图书信息
router.delete('/books/:id',service.deleteBook);
// 验证图书名称是否存在
router.get('/books/book/:name',service.checkName);
module.exports = router;
const data = require('./data.json');
const path = require('path');
const fs = require('fs');
// 自动生成图书编号(自增)
let maxBookCode = ()=>{
let arr = [];
data.forEach((item)=>{
arr.push(item.id);
});
return Math.max.apply(null,arr);
}
// 把内存数据写入文件
let writeDataToFile = (res) => {
fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(data,null,4),(err)=>{
if(err){
res.json({
status: 500
});
}
res.json({
status: 200
});
});
}
// 验证图书名称是否存在
exports.checkName = (req,res) => {
let name = req.params.name;
let flag = false;
data.some(item=>{
if(name == item.name) {
flag = true;
return true;
}
})
if(flag) {
res.json({
status: 1
})
}else{
res.json({
status: 2
})
}
}
// 获取图书列表数据
exports.getAllBooks = (req,res) => {
res.json(data);
}
// 添加图书保存数据
exports.addBook = (req,res) => {
// 获取表单数据
let info = req.body;
let book = {};
for(let key in info){
book[key] = info[key];
}
book.date = 2525609975000;
book.id = maxBookCode() + 1;
data.push(book);
// 把内存中的数据写入文件
writeDataToFile(res);
}
// 跳转编辑图书页面
exports.toEditBook = (req,res) => {
let id = req.params.id;
let book = {};
data.some((item)=>{
if(id == item.id){
book = item;
return true;
}
});
res.json(book);
}
// 编辑图书更新数据
exports.editBook = (req,res) => {
let info = req.body;
info.id = req.params.id;
data.some((item)=>{
if(info.id == item.id){
for(let key in info){
item[key] = info[key];
}
return true;
}
});
// 把内存中的数据写入文件
writeDataToFile(res);
}
// 删除图书信息
exports.deleteBook = (req,res) => {
let id = req.params.id;
data.some((item,index)=>{
if(id == item.id){
// 删除数组的一项数据
data.splice(index,1);
return true;
}
});
// 把内存中的数据写入文件
writeDataToFile(res);
}
[
{
"id": "4",
"name": "红楼梦",
"date": 2525609975000
},
{
"name": "三国演义",
"date": 2525609975000,
"id": 5
},
{
"name": "水浒传",
"date": 2525609975000,
"id": 6
},
{
"name": "西游记",
"date": 2525609975000,
"id": 7
},
{
"name": "www",
"date": 2525609975000,
"id": "8"
}
]
<!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 () {
// axios.get('books').then((data)=>{
// console.log(data.data)
// this.books = data.data;
// })
this.queryData();
},
});
</script>
</body>
</html>
更多推荐
所有评论(0)