Vue 第 3 天 - 计算属性、网络请求、生命周期及动画
以下内容转载自博主Serein的原创文章,遵循 CC 4.0 BY-SA 版权协议。
视频链接,代码链接 请跳转到下方链接
原文链接
01 - 计算属性 computed
手册 https://cn.vuejs.org/guide/essentials/computed.html
任何复杂逻辑,你都应当使用计算属性,计算属性是 Vue 的一个非常非常利好的特性。模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护
- computed 和data 平级。计算属性作为 computed 里面的一个方法,必须 return。
- 使用的时候和 data 里面的属性一样。
- 计算属性所依赖的属性(data中数据)有变化的时候,计算属性会重新计算。
基本使用,逻辑都写在行内,臃肿!
<body>
<div id="app">
<span>{{ author.books.length > 0 ? author.name : '啥也没有' }}</span>
</div>
<script type="module">
import { createApp } from './vue.js';
createApp({
data() {
return {
author: {
name: '路遥',
books: [
'平凡的世界',
'人生',
]
}
}
}
}).mount('#app')
</script>
</body>
将内容都写在computed中
this.publishedBooksMessage
依赖于 this.author.books
,所以当 this.author.books
改变时,任何依赖于 this.publishedBooksMessage
的绑定都将同时更新。
<body>
<div id="app">
<span>{{publishedBooksMessage }}</span>
</div>
<script type="module">
import { createApp } from './vue.js';
createApp({
data() {
return {
author: {
name: '路遥',
books: [
'平凡的世界',
'人生',
]
}
}
},
computed: {
// 方法名就是标签内引用的名字
publishedBooksMessage() {
return this.author.books.length > 0 ? this.author.name : '啥也没有'
}
}
}).mount('#app')
</script>
</body>
结合日期插件的实现
moment为日期插件,专门用于格式化时间
<body> <div id="app"> <h2>成为京东会员的日期:{{ date }}</h2> <input type="text" v-model="date" /> <h2>格式化后的日期 {{ formatDate }}</h2> <h2>您已经京东会员{{ vipDays }}天</h2> </div> <script src="./moment.js"></script> <script type="module"> import { createApp } from './vue.js'; createApp({ data() { return { date: '2019-8-8 8:05' } }, computed: { // 方法名就是标签内引用的名字 formatDate() { return moment(this.date).format('YYYY-MM-DD HH:mm:ss a') }, vipDays() { console.log('重新计算') return Math.ceil((Date.now() - new Date(this.date)) / (24 * 60 * 60 * 1000)) } } }).mount('#app') </script> </body>
02 - Demo 品牌管理
需求分析
- 基础 对象数组 v-for 渲染到页面上
- 表单输入 v-model
- @keyup.enter 绑定事件
- 通过计算属性计算需要显示的数据
- 点击 新增品牌 @click 展示弹窗
- 输入内容, push 进数组
注意事项
- 品牌列表是一个过滤的数组,过滤条件是品牌名称包含搜索的关键词。
- 计算属性可以用在 for 里面。
- 字符的非空判断建议用
if(!str)
等价于if(str=='')
。- Array 的 filter 返回一个符合条件的所有元素的新数组。
let arr =[4,6,67,78,234,345,33,543,53,34,34,534,53,534,5,345] let filterArr = arr.filter(function(item){ console.log(item) return item>50 }) console.log(arr,filterArr)
1. 展示列表 1. 品牌列表数组 brandList:[ { name:'小米', time:'2019-07-26 10:36:38 am' }, { name:'红米', time:'2019-07-24 10:36:38 am' } ] 2. 列表展示: v-for tr 2.删除一项 1. 点击事件 @click:delBrand(index) 2. 数组移除元素 brandList.splice(从哪一个元素开始删除,删除多少个) 3.新增品牌 1.弹层的显示与隐藏 1. 弹层 v-show="isShow" 1. 点击新增品牌,显示 @click isShow=true 2. 添加与取消 隐藏 @click isShow=false 2.新增品牌 1. v-model.trim:inputVal 2. @keyup.enter或者添加 addBrand 3. brandList.push({ name:'商品名称', time: 当前的时间 }) 4.搜索功能 1.v-model.trim:keywords 2.计算属性 filterBrandList 1. brandList根据keywords过滤后数组 item.name.includes(keywords
03- promise 异步处理
在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现.
div.onclick = function(){}
Promise使ES6中引入的一个异步编程解决方案,与传统的ES5方法相比它的结构更合理,功能更强大.
特点
Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态.
语法:
var p = new Promise(function(resolve,reject){})
resolve 代表 决定(成功); reject 代表 失败
使用
const p = new Promise(function(resolve,reject){
setTimeout(function(){
// resolve('我是成功的')
reject('这是失败的');
},2000)
});
.then(callback)的使用(成功时调用)
.catch(callback的用法(失败时调用)
p.then(function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
}).catch(function(reason, data){
console.log('catch到rejected失败回调');
console.log('catch失败执行回调抛出失败原因:',reason);
});
效果和写在then的第二个参数里面一样。它将大于10的情况下的失败回调的原因输出
注意:resolve和reject的两种状态
resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
结合函数
我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数
let promiseFn =()=>{
console.log('点击方法被调用')
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成Promise');
resolve('成功的时候调用');
}, 2000);
});
return p
}
promiseFn().then(function(data){
console.log(11111)
}).catch(function(data){
console.log(2222)
})
静态方法的使
04 - 网络请求原生 XMLHttpRequest
- 浏览器对 XMLHttpRequest 对象的支持度不足, 创建 XMLHttpRequest 对象时需要对 IE 做兼容,XMLHttpRequest 本质上来讲其实也是一个事件监听行为。
- readyState
- 0-4,0表示未初始化,4表示请求已完成
- status(HTTP响应状态码)
- 200:OK,成功
- 3XX【重定向系列的状态码】
- 301:永久重定向
- 302:临时重定向
- 307:内部浏览器(缓存)重定向
- 4XX【错误系列】
- 400:bad request,错误请求
- 401:鉴权失败
- 403:禁止访问
- 404:找不到对应的资源
- 405:方法不被允许
- 5XX【服务器错误,环境问题】
- 500:服务器内部错误(代码、环境问题)
- 502:bad Getway,错误网关
- 案例:使用XHR请求全国高校数据接口
接口地址
- https://api.i-lynn.cn/college
- 只循环展示
list
信息即可- 接口可以直接被跨域请求
案例效果
- 参考代码:
<body> <div id="app"> <ul> <li :key='index' v-for='(el,index) in list'>{{el.area}}:{{el.counts}}所</li> </ul> </div> </body> <script src="./js/vue.js"></script> <script> new Vue({ el: '#app', data: { list: [] }, mounted: function(){ // 1. 创建xhr对象 var xhr = new XMLHttpRequest() const api = 'https://api.i-lynn.cn/college' // 2. 绑定回调函数 xhr.onreadystatechange = () => { // 3. 判断是否成功 if(xhr.readyState == 4 && xhr.status == 200){ this.list = JSON.parse(xhr.responseText).list } } // 4. 打开请求 xhr.open('GET',api) // xhr.open('POST',api) // 设置请求头 // xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); // 5. 发送请求 xhr.send() // xhr.send("username=111&age=222") } }) </script>
后期学习的
PUT
、DELETE
等特殊的请求动词都会触发预检请求。
05 - 网络请求 axios
axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。axios 是 vue 作者推荐使用的网络请求库,它具有以下特性:
- 支持浏览器和 node.js
- 支持 promise
- 能够拦截
请求和响应
- 自动转换 json 数据
axios 的浏览器支持。
- axios 使用,先导包,再用包。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
// GET请求方式 axios.get('/get_data?id=10010').then(ret => console.log(ret.data)) axios.get('/get_data',{ params: { id: 10010, name: 'zhangsan', age: 26 } }).then(ret => console.log(ret.data)) //POST请求方式 axios.post('/set_data', { firstName: 'zhang', lastName: 'san' }).then(ret => { }) axios({ method: 'post', url: 'set_data', timeout: 1000, headers: {'X-Custom-Header': 'foobar'}, data: { firstName: 'zhang', lastName: 'san' } }).then(ret => { })
当然 axios 除了支持传统的
GET
和POST
方式以外,常见的请求方式还支持:
- put:修改数据
- delete:删除数据
以上方的 axios 请求示例为例,axios 响应结果(
res
)的主要属性有:
- data:实际响应回来的数据(最常用)
- headers:响应头信息
- status:响应状态码
- statusText:响应状态信息
在使用 axios 发送请求之前它允许我们通过全局配置做一些设置,这样可以方便后续的请求操作,例如:
axios.defaults.timeout = 3000
【设置超时时间】axios.defaults.baseURL = 'http://localhost/app'
【设置默认地址】axios.defaults.headers['_token'] = '123123123'
【设置请求头信息,通用头信息】
_axios.defaults.headers.get['_token'] = '123123'
axios.defaults.headers.post['_token'] = '123123'
axios.defaults.headers.common['_token'] = '123123'
【通用头信息,common可以不写】注意事项
- axios发送post请求的时候,默认发送json格式数据
- 如果需要发送post表单类型请求,则需要指定请求头
axios.post('college',{ username: 'zhangsan', age: 22 },{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }).then(ret => this.list = ret.data.list)
06 - 网络请求 axios 拦截器
**目的:**在请求
发出去之前
/收到响应之后
做一些操作
- 请求拦截器
示例代码:
axios.interceptors.request.use(function(config){ // 在请求发出去之前进行一些信息设置 return config; },function(err){ // 处理响应的错误信息 });
- 响应拦截器
示例代码:
axios.interceptors.response.use(function(res){ // res为axios对象 return res; },function(err){ // 处理响应的错误信息 });
- axios 和 ajax 的区别
- ajax 使用的是 success、error 回调函数作为参数来使用的,如果回调层级过多,就会造成非常不好的代码体验,稍有不慎还有可能造成 回调地狱(无限调用)。
- axios 使用的是链式调用,什么是链式调用?正如我们上面的体验
then、catch、finally
是可以不断的被调用下去的。- axios 在链式调用的参数方法定义中,使用箭头函数确保能够绑定到当前 vue 实例上并能够顺利的调取 vue 声明的属性和方法。
- 如果说,我们不使用箭头函数,则需要在外围声明一个新的变量
let that = this
,然后使用that来代表当前 vue 实例。- 我们也可以配合使用 async await 来实现更加友好舒适的请求调用。
07-天气预报
- 需求分析
- 输入城市,显示搜索城市
- 获取输入的城市 v-model
- 点击回车 enter 键,响应 @keyup.enter
- 使用axios请求天气
- 使用 v-for 展示天气搜索结果
/*
1. 显示搜索城市
1. v-model:city
2. {{city}}
2. 输入城市,回车,请求
1. @keyup.enter:queryWeather
2.axios https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=43656176&appsecret=I42og6Lm&ext=&cityid=&city=%E9%83%91%E5%B7%9E
3. 展示天气搜索结果
1. forecastList[]
2. v-for
3. v-if
*/
<body>
<div id="app">
<h2>天气查查</h2>
<input type="text" v-model="city" @keyup.enter="getWeather">
<input type="button" @click="getWeather" value="查询">
<p v-for="(v,k) in weatherData">{{v.day}} {{v.narrative}}</p>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="module">
import { createApp } from './vue.js';
createApp({
data: function () {
return {
isShow: true,
city: '郑州',
weatherData: []
}
},
methods: {
getWeather() {
axios.get('https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=43656176&appsecret=I42og6Lm&ext=&cityid=&city=' + this.city)
.then(({ data }) => {
// console.log(data);
this.weatherData = data.data;
})
.catch(function (error) {
console.log(error);
});
}
}
}).mount('#app')
</script>
</body>
08- Vue 生命周期钩子
文档 https://cn.vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram
声明周期的概念
每个 Vue 实例在被创建之前都要经过一系列的初始化过程。
例如需要设置数据监听、编译模板、挂载实例到 DOM,在数据变化时更新 DOM 等。
同时在这个过程中也会运行一些叫做生命周期钩子的函数,目的是给予用户在一些特定的场景下添加他们自己代码的机会。
Vue生命周期的主要阶段:
- 挂载(初始化相关属性)
beforeCreate
- 注意点:在此时不能获取data中的数据,也就是说
this.msg
得到的是undefined
created
一般用于发送ajax请求
beforeMount
mounted【页面加载完毕的时候就是此时】
- 注意点:默认情况下,在组件的生命周期中只会触发一次
- 更新(元素或组件的变更操作)
- beforeUpdate
- updated
- 注意点:可以重复触发的
10 - 课后作业
- 灵活使用计算属性 computed
- 认真掌握网络请求 axios
- 理解 Vue 生命周期