Vue生命周期
虚拟节点
虚拟节点的概念,方便理解视图框架(Vue、React、小程序)
目前流行视图框架都是基于虚拟节点技术开发的
jq落伍是因为jq里DOM操作性能不好。
而视图框架 更新视图的最后一步是DOM操作,尽量以最低代价进行DOM操作,
视图框架如何进行最低代价的DOM操作 => 虚拟节点 => 虚拟节点的更新 => diff算法.
虚拟节点在描述一个标签时,都有3个最基本的属性 => 标签名,属性列表,子节点列表。
虚拟节点就是真实节点的js描述.(AST语法树)
Vue实例的虚拟节点:console.log(vm._vnode)
生命周期
Vue的生命周期 Vue实例从创建达到销毁的过程中的特定阶段
创建前,创建后,挂载前,挂载后 都只触发一次(在实例化的过程中)
生命周期图示:
你描述下Vue的生命周期.(Vue的钩子函数).
1:基本的回答 => 8个钩子函数的名字.(不懂英文说中午).
2:回答生命周期图示.(更详细).
new Vue实例化(组件实例化)
触发beforeCreate
通过Object.defineProperty给data数据设置数据劫持
触发created
判断有没有el选项.
如果有,继续判断有没有template选项
如果有template选项,则编译template
如果没有template选项,则编译el所在的标签
触发beforeMount
根据编译的虚拟节点生成真实节点vm.$el.并且用真实的新视图替换掉老视图
触发mounted.
如果没有el选项,则等待$mount方法触发,如果这个方法也没触发,则实例化失败.
创建期
创建期有 创建前beforeCreate()
和创建后created()
两个函数
创建 给vue实例添加数据 给data设置数据劫持
创建前后即是数据劫持前后
new Vue({
el: '#app',
data: {
msg: ''
},
// 创建前 => 没什么用.
beforeCreate() {
console.log('创建前');
console.log('beforeCreate', this.$data); // undefined
},
// 创建后 => 一帮用于数据初始化。
// 在这个构造函数内只能操作数据,不能操作视图.
created() {
console.log('创建后');
console.log('created', this.$data);
this.msg = '吴签';
},
})
挂载期
挂载 新视图替换老视图
挂载前后 新视图出现前后
mounted 视图初始化
挂载都发生了什么事情?
- 编译template(把字符串模板编译成虚拟节点)
- 编译遇到指令和插值表达式,会进行求值(收集依赖)
- 把虚拟节点转为新视图,替换老视图
// created => 处理数据(默认处理一次)
// mounted => 处理视图(默认处理一次)
new Vue({
el: '#app',
data: {
msg: '按钮'
},
template: `<button>{{msg}}</button>`,
created() {
console.log('created');
},
// 新视图挂载前 (老视图最终会被删除,数据不会显示在老视图上);
beforeMount() {
console.log('挂载前');
},
// 新视图挂载后.(数据显示到了视图上);
mounted() {
console.log('挂载后');
}
})
销毁期
destroyed => 组件销毁后的善后处理,例如停止定时器
组件销毁只是让数据不去动视图更新,组件实例还在
因此在组件的定时器还会继续
const box = {
template: `<h3>box组件--{{count}}</h3>`,
data() {
return { count: 0 }
},
// 销毁前
beforeDestroy() {
console.log('销毁前')
},
// 销毁后
destroyed() {
console.log('销毁后');
// 销毁后关闭定时器
clearInterval(this.id);
},
created() {
console.log('创建后');
// 记录当前的定时器id.
this.id = setInterval(() => {
// console.log(this.count);
this.count++
},1000);
},
mounted() {
console.log('挂载后')
}
}
视图更新过程
数据变化 => 导致视图更新 (响应式)
数据变化 => 先更新虚拟节点 => diff算法判断 => 最后更新真实节点。
更新真实节点
1:原地更新.(标签不增删,不移动,直接修改内容或者属性)
2:替换更新.(会增删,移动元素)
什么时候原地更新?什么时候替换更新?
1:比较更新前后的虚拟节点.(同级比较)
2:如果同级的tag一致,并且key一样,则表示更新前后是同一个标签,使用原地更新策略.
3:如果同级的tag或者key有一个不一样,则表示更新前后不是同一个标签,使用替换更新策略.
key
如果tag和key一致,就原地更新
只要给上不一样的key,则使用替换更新策略
以后v-for都要加key => 数据更新 和视图更新保持一致,需要加key,保证更新前后的key不一致
v-if和v-show
对于多次显示隐藏的标签,应该用v-show
对于只有一次显示隐藏的,应该用v-if
v-for和v-if的优先级
v-for优先级更高 => 不管有没有虚拟节点,都会循环 => 性能不好.不推荐v-for和v-if一起使用.
<div id='app'>
<ul>
<li v-for='d in arr' v-if='d%2 === 0'>{{d}}</li>
</ul>
<ul>
<li v-for='d in arr.filter(item => item%2 === 0)'>{{d}}</li>
</ul>
<ul>
<li v-for='d in list'>{{d}}</li>
</ul>
</div>
const vm = new Vue({
el: '#app',
data: {
arr: [111, 222, 333, 444]
},
computed: {
list() {
return this.arr.filter(item => item%2 === 0)
}
}
})