目录
前言
上一章博客我们讲解了Vue基础
这一章我们来讲Vue生命周期,列表过滤,计算属性和监听器
一,生命周期
- 通常也叫生命周期回调函数、生命周期函数、生命周期钩子
- vue初始化时在不同的阶段调用的不同函数
- 生命周期函数的
this
指向为vue实例,名字不能更改
1.1,生命周期函数简介
“生命周期”指实例对象从构造函数开始执行(被创建)到被GC(Garbage Collection)回收销毁的整个存在的时期
生命周期函数是为了在实例对象的各个阶段方便开发者控制而产生,在不同的时期有不同的生命周期函数,可以利用不同时期的生命周期函数去完成不同的操作
实际的开发过程中,生命周期函数的使用较为频繁,需要重点掌
1.2,Vue的初始化流程
- beforeCreate阶段 - vue中data的数据和methods的方法还不能使用
- created阶段 - vue中data的数据和methods的方法已可以使用
- beforeMount阶段 - 页面可以展示内容,但是是未编译,最终都是不能操作的DOM结构,展示时间短
- mounted - 页面显示编译后的DOM- vue的初始化过程结束- 此阶段可进行:定时器、网络请求、订阅消息、绑定事件等
1.3,Vue的更新流程
- beforeUpdate - 数据是新的,页面还没有更新
- Updated - 数据是新的,页面同步更新
1.4, Vue的销毁流程
- beforeDestroy - 此阶段可关闭定时器和取消订阅- 数据、方法可以访问但是不触发更新
- destroy - 一切都结束了
1.5, 回顾生命周期
- 生命周期函数 - 创建前、创建后(beforeCreate、created)- 挂载前、挂载后(beforeMount、mounted)- 更新前、更新后(beforeUpdate、updated)- 销毁前、销毁后(beforeDestroy、destroyed)
- 常用的生命周期函数 - mounted - 开启定时器- 发送ajax请求- 订阅消息- 绑定自定义事件- beforeDestroy - 清除定时器- 取消订阅、事件监听- 解绑自定义事件
- vue实例销毁 - vue开发者工具的数据为空- 销毁后自定义事件失效- 不要在beforeDestroy进行数据的操作,不会再走更新流程
1.,6,代码演示
1.6-1,beforeCreate
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},beforeCreate(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
// beforeCreate中,data的数据是没有被定义的
console.log("beforeCreate",this.myName,bobyDom);},})</script></html>
1.6-2,created
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},created(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
// 做一下页面的数据初始化工作。比如说发起ajax请求
console.log("created",this.myName,bobyDom);},})</script></html>
1.6-3,beforeMount
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},beforeMount(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
console.log("beforeMount",this.myName,bobyDom);},})</script></html>
1.6-4,mounted
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},mounted(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
// 数据已经渲染到View中
console.log("mounted",this.myName,bobyDom);},})</script></html>
1.6-5,beforeUpdate
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},beforeUpdate(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
// 数据更新前,数据未改变
console.log("beforeUpdate",this.myName,bobyDom);},})</script></html>
1.6-6,updated
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app">
{{myName}}
</div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{myName:"abc"}},updated(){var bobyDom = document.getElementsByTagName("body")[0].innerHTML
// 数据更新后,数据已改变
console.log("updated",this.myName,bobyDom);}})</script></html>
1.7,生命周期函数的使用场景
- 在beforeCreate生命周期函数运行时,可以添加loading动画
- 在created生命周期函数运行时,可以结束loading动画,还可以做一些初始化,实现函数自执行等操作
- 最经常使用的是mounted生命周期函数 - 可以发起后端数据请求,取回数据- 可以接收页面之间传递的参数- 可以子组件向父组件传递参数等
二,vue中列表排序
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><div><inputtype="text"v-model="searchInput"name=""id=""><button@click="paixu(1)">升序</button><button@click="paixu(2)">降序</button><button@click="paixu(3)">原序列</button><divv-for="(item,index) in searchList">
{{item.name}}--{{item.price}}
</div></div></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:'#app',data(){return{keyword:0,// 用来排序searchInput:"",goodList:[{name:'牛仔裤',price:200},{name:'运动鞋',price:100},{name:'跑步鞋',price:300},{name:'篮球鞋',price:400},],}},methods:{paixu(val){this.keyword=val
}},computed:{searchList(){// 把goodList的内容过滤,把符合条件的形成一个新的数组// filter是数字的过滤方法,这个方法的参数是一个函数,此函数返回true,则把此项返回新的数组中let list =this.goodList.filter((item)=>{return item.name.indexOf(this.searchInput)!==-1})if(this.keyword){
list.sort((a1,a2)=>{returnthis.keyword ===1? a1.price - a2.price
: a2.price - a1.price
})}return list
}}})</script></html>
2.1,vue中数据更新的问题
2.1-1,对象新增数据更新问题
- 描述 - 通过普通对象添加属性方法,Vue不能监测到且不是响应式
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><divv-for="(attr,key) in person">
{{key}} -- {{attr}}
</div></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:'#app',data(){return{person:{name:'张三',sex:'男',}}},})</script></html>
这样添加它没有没有跟对象一样封装有监测数据变化的getter、setter
- 解决 - Vue.set() / this.$set
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><divv-for="(attr,key) in person">
{{key}} -- {{attr}}
</div></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:'#app',data(){return{person:{name:'张三',sex:'男',}}},})</script></html>
- 注意 - this.$set不能给vue实例的根数据对象添加属性
2.1-1,数组数据更新问题
- 描述 - 直接通过数组索引值改变数组的数据,Vue监测不到改变- 实际在
js
内存已经把数据的第一项数据修改了
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><divv-for="(attr,key) in person">
{{key}} -- {{attr}}
</div><div><inputtype="text"v-model="searchInput"name=""id=""><button@click="paixu(1)">升序</button><button@click="paixu(2)">降序</button><button@click="paixu(3)">原序列</button><divv-for="(item,index) in searchList">
{{item.name}}--{{item.price}}
</div></div></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:'#app',data(){return{keyword:0,// 用来排序searchInput:"",goodList:[{name:'牛仔裤',price:200},{name:'运动鞋',price:100},{name:'跑步鞋',price:300},{name:'篮球鞋',price:400},],person:{name:'张三',sex:'男',}}},methods:{paixu(val){this.keyword=val
}},computed:{searchList(){// 把goodList的内容过滤,把符合条件的形成一个新的数组// filter是数字的过滤方法,这个方法的参数是一个函数,此函数返回true,则把此项返回新的数组中let list =this.goodList.filter((item)=>{return item.name.indexOf(this.searchInput)!==-1})if(this.keyword){
list.sort((a1,a2)=>{returnthis.keyword ===1? a1.price - a2.price
: a2.price - a1.price
})}return list
}}})</script></html>
- 原因 - 因为在vue中数组并没有跟对象一样封装有监测数据变化的getter、setter
- 解决 - Vue在数组的原始操作方法上包裹了重新解析模板的方法,也就是说我们在data里面的数组操作方法不是原生的,是vue封装过的- 哪些数组操作方法经过了封装?
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
pop() 删除数组的最后一个元素并返回删除的元素
shift() 删除并返回数组的第一个元素
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
splice() 从数组中添加或删除元素。
sort() 对数组的元素进行排序
reverse() 反转数组的元素顺序。
三,计算属性computed
计算属性,方法名可以直接在对象中使用.这个属性是通过计算得出的。
这个方法中的任意属性改变,都会触发这个方法
使用场景:希望把一些计算的业务逻辑放在方法中,例如:全名计算、地址计算、购物车合计
下面的示例,我们使用了三种方式:
- 使用方法实现
- 使用vue的computed读写方式实现
- 使用vue的computed只读方式实现
注意:推荐使用computed的方式。有缓存机制。在页面重复调用多次的情况下,只执行一次
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><div><inputtype="text"v-model="firstName"><br><inputtype="text"v-model="lastName"><br><inputtype="text"v-model="getFullName()"><br><inputtype="text"v-model="fullNameReadOnly"><br><inputtype="text"v-model="funName"><br></div></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{firstName:'科比',lastName:'布莱恩特',}},methods:{getFullName(){returnthis.firstName +"-"+this.lastName
}},computed:{// 只读方式的简写fullNameReadOnly(){returnthis.firstName +"-"+this.lastName
},funName:{get(){returnthis.firstName +"-"+this.lastName
},set(value){this.firstName = value.split("-")[0]this.lastName = value.split("-")[1]}}},})</script></html>
四,监视属性watch
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"></div></body><scriptsrc="../js/vue2.7.js"></script><script>var app =newVue({el:"#app",data(){return{isSunny:true,person:{age:18,name:'王导',}}},watch:{// 表示要对isSunny这个属性进行监听isSunny(newVal,oldVal){
console.log("改变了",oldVal,newVal);},// 深度监听可以用来监听整个对象的改变,但要慎重使用,因为消耗性能 person:{deep:true,handler(oldVal,newVal){
console.log("改变了",oldVal,newVal);}},"person.name"(oldVal,newVal){
console.log("我也监听了");}}})</script></html>
最后
送大家一句话: 世界上的好东西都是抢来的,只有弱者才会坐等分配
版权归原作者 天秤座的码农 所有, 如有侵权,请联系我们删除。