Vue前端框架学习笔记(3)(完结)
VUE2.5前端框架学习笔记(前后端交互)
(一)前后端交互模式
-
接口调用方式
●原生 ajax
●基于 jQuery的ajax +
●fetch (重点)
●axios(重点) -
URL地址格式
格式: schema://host:port/path?query#fragment
1.传统形式的URL - ①schema: 协议。例如http、https、 ftp等
②host: 域名或者IP地址
③port: 端口,http默认端口80,可以省略
④path: 路径,例如/abc/a/b/c(并不代表服务器中有这样层次的目录,只是虚拟的,用来区分不同的资源)
⑤query :查询参数,例如uname=lisi&age=12
⑥fragment: 锚点(哈希Hash),于定位页面的某个位置 - eg:http://www.itcast.cn/java/web?flag= 1#function
2.Restful形式的URL(与提交方式密切相关)
- HTTP请求方式
①GET查询
②POST添加
③PUT修改
④DELETE删除 - eg:http://www.hello.com/books GET
http://www.hello.com/books POST
http://www.hello.com/books/123 PUT (修改id=123这本书的信息)
http://www.hello.com/books/123 DELETE(删除id=123这本书)
(这种url地址可以\直接传参,请求方式不同时对应不同的url)
(二)Promise(用来解决异步调用顺序混乱问题)
-
异步调用是什么
异步效果分析
①定时任务
②Ajax
③事件函数 -
多次异步调用的依赖分析
●多次异步调用的结果顺序不确定
●异步调用结果如果存在依赖需要嵌套(嵌套就是把下面的代码写成层层递进的形式)//同时发送多个ajax请求从后端接口调取数据 $. ajax({ url:'http://localhost:3000/data', success: function(data) { //回调函数 console.log(data); } }); $. ajax({ url:'http://localhost:3000/data1', success: function(data) { console.log(data); } }); $. ajax({ url:'http://localhost:3000/data2', success:function(data) { console.log(data) ; } });
//后端路由接口(路由后面会讲) app.get('/data', (req, res) => { res.send('Hello World!') }) app.get('/data1', (req, res) => { res.send('Hello TOM!') I }) app.get('/data2', (req, res) => { res.send('Hello JERRY!') })
运行结果:不确定,三者顺序会颠倒
promise概述
Promise是异步编程的一种解决方案,从语法上讲, Promise是一个对象,从它可以获取异步操作的消息。
使用Promise主要有以下好处:
●可以避免多层异步调用嵌套问题(回调地狱)
●Promise 对象提供了简洁的API,使得控制异步操作更加容易
promise用法
实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务
resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果
//使用示例 var P = new Promise (function (resolve, reject){ //成功时调用resolve() //失败时调用reject () }); p.then(funciton(ret) { //从resolve得到正常结果 },function(ret) { //从reject得到错误信息 });
//实际使用情况 var p = new Promise(function(resolve, reject){ //这里用于实现异步任务 setTimeout(function(){ var flag = false; //true if(flag) { //正常情况 resolve(' hello'); }else{ //异常情况 reject('出错了'); },100); }); p. then(function(data){ console.log(data) }, function(info){ console.log(info) });
基于Promise处理Ajax请求
//基于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) });
then参数中的函数返回值
返回Promise实例对象返回的该实例对象会调用下一 个then
返回的普通值会直接传递给下一个then,通过then参数中函数的参数接收该值
promise常用API
1.实例方法
p.then()得到异步任务的正确结果
p.catch()获取异常信息
p.finally()成功与否都会执行(尚且不是正式标准)
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') });
运行结果:
123
finished 或
error
finished
2.对象方法
Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果
使用模板:
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-对象方法*/ 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> //后台接口 app. get('/a1',(req, res) => { setTimeout(function(){ res.send('Hello TOM!') }, 1000); }) app. get('/a2',(req, res) => { setTimeout(function(){ res.send('Hello JERRY!') }, 2000); }) app. get('/a3', (req, res) => { setTimeout (function(){ res.send('Hello SPIKE!') }, 3000); })
(三)接口调用-fetch用法
-
fetch概述
1.基本特性
更加简单的数据获取方式,功能更强大、更灵活,可以看做是原生ajax的升级版
基于Promise实现
2.语法结构fetch(ur1).then(fn2) .then(fn3) .... .catch (fn)
-
fetch的基本用法
fetch('/abc').then (data=> { return data.text(); }).then(ret=>{ //注意这里得到的才是最终的数据 console.log (ret); }) ;
实例:
/*Fetch API 基本用法*/ fetch('http://localhost:3000/fdata').then(function(data){ // text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据 return data.text(); }).then(function(data){ console.log(data); })
-
fetch API参数传递
常用配置选项
method(String):HTTP请求方法,默认为GET(GET、POST、PUT、DELETE)
body(String): HTTP的请求参数
headers(Object): HTTP的请求头,默认为{}fetch('/abc',( method: 'get' }) .then (data=> { return data.text(); }) .then(ret=>{ //注意这里得到的才是最终的数据 console.log(ret); });
GET
传统get://后台接口 app.get('/books',(req, res) => { res.send('传统的URL传递参数!' + req.query.id) }) //GET参数传递-传统URL fetch('http://localhost:3000/books?id=123', { method: 'get' }) .then(function(data){ return data.text(); }).then(function(data){ console.log(data) });
Restful形式:
//后台接口 app.get('/books/:id', (req, res) => { res.send('Restful形式的URL传递参数!'+ req.params.id) }) //GET参数传递-restful形式的URL fetch('http://localhost:3000/books/456', { method: 'get' }) .then(function(data){ return data.text(); }).then(function(data){ console.log(data) });
-
DELETE
//后台接口 app.delete('/books/:id', (req, res) => { res.send(' DELETE请求传递参数! + req.params.id) }) // DELETE请求方式参数传递 fetch('http://localhost:3000/books/789', { method: 'delete' }) .then(function(data){ return data.text(); }).then(function(data){ console.log(data) });
-
POST
//后台接口 app.post('/books', (req, res) =>{ res.send('POST请求传递参数!' + req.body.uname + '---' + req.body.pwd) }) //POST请求传参方法1 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请求传参方法2 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) });
-
PUT
//后台接口 app.put( '/books/:id', (req, res) =》{ res.send('PUT请求传递参数!' + req.params.id + '---' + req.body.uname + '---' + req.body pwd) }) // PUT请求传参 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) });
fetch响应结果
text():将返回体处理成字符串类型
json():返回结果和JSON.parse(responseText)一样
//后台接口 app. get('/json', (req,res) => { res.json({ uname:'lisi' , age: 13, gender:'male' }); }) /*Fetch响应结果的数据格式*/ fetch('http://localhost:3000/json').then(function(data){ // return data.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) })
(四)接口调用-axios用法(公司用)
-
axious基本特性
axios (官网: https://github.com/axios/axios) 是一个基于Promise用于浏览器和node.js的HTTP客户端,需要导入包才能使用。
它具有以下特征:
●支持浏览器和nodejs
●支持promise
●能拦截请求和响应
●自动转换JSON数据(后台传递的json数据不用转换就直接用) -
axious的基本用法
axios.get('/adata') .then (ret=> { // data属性名称是固定的,用于获取后台响应的数据 console.log (ret.data) })
axios.get('http://localhost:3000/adata').then(function(ret){ // 注意data属性是固定的用法,用于获取后台的实际数据 console.log(ret.data) //console.log(ret) //ret本身包含了一系列的属性 })
-
axious的常用API
get:查询数据
post:添加数据
put:修改数据
delete:删除数据get传递参数
通过URL传递参数,两种形式//后台接口 app.get('/axios', (req,res) => { res.send('axios get传递参数' + req.query.id) }) axios.get('http://localhost:3000/axios?id=123').then(function(ret){ console.log(ret.data) })
//后台接口 app.get('/axios/:id', (req, res) => { res.send('axios get (Restful) 传递参数'+ req.params.id) }) axios.get('http://localhost:3000/axios/123').then(function(ret){ console.log(ret.data) })
通过params选项传递参数
//后台接口 app.get('/axios', (req,res) => { res.send('axios get传递参数' + req.query.id) }) //前端代码 axios.get('http://localhost:3000/axios', { params: { id: 789 } }).then(function(ret){ console.log(ret.data) })
-
delete传递参数
和get的相似,get改成delete就可。//后台接口 app.delete('/axios', (req, res) => { res.send('axios get 传递参数'+ req.query.id) }) //axios delete 请求传参 axios.delete('http://localhost:3000/axios', { params: { id: 111 } }).then(function(ret){ console.log(ret.data) })
-
post传递参数
通过选项传递参数(默认传递的是json格式的数据)//接口 app.post('/axios', (req, res) => { res.send('axios post传递参数' + req.body.uname + ---' + req.body.pwd) }) //前端代码 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) })
-
put传递参数
put传递参数与post类似
通过选项传递参数(默认传递的是json格式的数据)// axios put 请求传参 axios.put('http://localhost:3000/axios/123', { 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.put('http://localhost:3000/axios', params).then(function(ret){ console.log(ret.data) })
注意:如果后台支持json的话还是使用jjson方式传参更加方便
axios的响应结果
-
响应结果的主要属性
●data:实际响应回来的数据
●headers:响应头信息
●status:响应状态码
●statusText:响应状态信息
axios的全局配置
axios.defaults.timeout = 3000; // 设置超时时间,过了这个时间前端默认后台出错 // 配置请求的基准URL地址 axios.defaults.baseURL = 'http://localhost:3000/app'; axios.get('axios-json').then(function(ret){ //路径可以简写了 console.log(ret.data.uname) }) // 配置请求头信息 axios.defaults.headers['mytoken'] = 'hello';
axios拦截器
1.请求拦截器(在请求发出之前设置一些信息)
2.响应拦截器(在获取数据之前对数据做一些加工处理)
/*axios拦截器*/ //请求拦截器 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) })
(五)接口调用-async/await用法
-
async/await的基本用法
async/await是ES7引入的新语法,可以更加方便的进行异步操作;
async关键字用于函数上(async函数的返回值是Promise实例对象);
await关键字用于async函数当中(await可以得到异步的结果)。//处理单个异步请求的实例 axios.defaults.baseURL = 'http:localhost:3000'; //第一种写法 async function queryData() { var ret = await axios.get('adata'); // console.log(ret.data) return ret.data; } //第二种写法 async function queryData() { var ret = await new Promise(function(resolve, reject){ setTimeout(function(){ resolve('nihao') },1000); }) // console.log(ret.data) return ret; } queryData().then(function(data){ console.log(data) })
//处理多个异步请求 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) })
(六)基于接口的案例
-
案例分析
●图书相关的操作基于后台接口数据进行操作
●需要调用接口的功能点
①图书列表数据加载 GET http://localhost:3000/books
②添加图书 POST http://localhost:3000/booos
③验证图书名称是否存在 GET http://localhost:3000/books/book/:name
④编辑图书-根据ID查询图书信息 GET http://oc alhost:3000/books/:id
⑤编辑图书提交图书信息 PUT http://localhost:3000/books/:id
⑥删除图书 DELETE http://localhost:3000/books/:id -
代码示例
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) { //过滤器,内容省略 }) 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 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)=>{ //一定要是箭头函数,看(1) // console.log(data.data) // this.books = data.data; // }) this.queryData(); } });
(七)附件:后台文档样式参考:
图书管理后台接口文档
基准路径: 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表示不存在) }
第三部分vue前端交互结束
b站Vue全家桶从入门到实战
- [学习笔记]vue-前端框架
- 十四周学习前端的Vue.js框架的笔记记录,以及遇到的问题记录。什么是Vue.js?
- 十五周学习前端的Vue.js框架的笔记记录,以及遇到的问题记录。
- 前端主流框架vue学习笔记第二篇
- 十六周学习前端的Vue.js框架的笔记记录,以及遇到的问题记录
- 前端主流框架vue学习笔记第一篇
- 【Web前端学习笔记】Web前端框架_JQuery
- web前端框架的学习(一)——vue项目
- bootstrap 前端框架学习笔记
- 3.VUE前端框架学习记录三:Vue组件化编码1
- web前端开发vue笔记学习
- Yii框架学习笔记(二)将html前端模板整合到框架中
- spring mvc 及NUI前端框架学习笔记
- 前端MVVM框架avalon学习笔记
- Web前端学习笔记:Bootstrap框架
- spring mvc 及普元nui前端框架学习笔记
- 前端主流框架学习——Vue高级
- Vue 项目基础框架学习笔记
- Web前端学习笔记:Bootstrap框架
- 前端学习笔记四:Vue(1)基本语法 + 条件语句 + 循环语句