个人自学前端28-Vue5-虚拟节点,生命周期
作者:互联网
一. 虚拟节点
目前流行的视图框架都是基于虚拟节点技术开发的.
视图框架 => 更新视图的最后异步是DOM操作. => 尽量以最低的代价进行DOM操作.
视图框架如何进行最低代价的DOM操作 => 虚拟节点 => 虚拟节点的更新 => diff算法.
虚拟节点 => 一个纯对象 => 描述真实节点.
虚拟节点在描述一个标签时,都有3个最基本的属性 => 标签名,属性列表,子节点列表。
虚拟节点就是真实节点的js描述.(AST语法树)
const Vnode = {
// 描述标签名
tag: 'div',
// 描述属性节点列表
attrs: [{id: 'app'}],
children: [{
tag: 'h3',
attrs: [],
children: ['Vue你好']
}]
}
console.log(vm._vnode);
真实节点更新 => 一定是DOM操作完成.
虚拟节点更新 => 修改纯对象.
如何根据更新后的虚拟节点,决定如何进行DOM操作去更新真实节点. => diff算法.
diff算法 => 比较更新前和更新后的虚拟节点一桶,最终决定如何进行DOM操作.
二. 生命周期
Vue的生命周期 => Vue实例从创建达到销毁过程中的特定阶段.
new Vue实例化(组件实例化)
触发beforeCreate
通过Object.defineProperty给data数据设置数据劫持
触发created.
判断有没有el选项.
如果没有el选项,则等待$mount方法触发,如果这个方法也没触发,则实例化失败.( $mount(选择器) === el: 选择器)
如果有,继续判断有没有template选项
如果有template选项,则编译template
如果没有template选项,则编译el所在的标签
触发beforeMount
根据编译的虚拟节点生成真实节点vm.$el.并且用真实的新视图替换掉老视图
触发mounted.进入运行阶段.
监控数据变化,触发beforeUpdate,updated
实例(组件DOM)销毁时,先调用beforeDestory
调用Destroyed,全部销毁
1. 创建期
创建 => 给vue实例添加数据 => 给data设置数据劫持.
创建前后 => 数据劫持前后.(Object.defineProperty进行数据劫持前后)
这两个钩子只会触发一次.
- beforeCreate
创建前 => 没什么用 - created
创建后 => 一般用于数据初始化。
在这个构造函数内只能操作数据,不能操作视图.
2. 挂载期
挂载 => 新视图替换老视图.(组件template替换组件标签).
挂载前后 => 新视图出现前后.
这两个钩子也只触发一次.
mounted => 视图初始化.
挂载都发生了什么事情?
- 编译template.(把字符串模板编译成虚拟节点).
- 编译遇到指令和插值表达式,都会进行求值.(收集依赖).
- 把虚拟节点转换为新视图,替换老视图.
3. 更新期
视图更新前后 => 分别触发beforeUpdate和updated
默认不触发(Vue实例化阶段不触发).
Vue实例化完成之后,视图再更新,才会触发.
有可能触发很多次.
- updated和watch的区别
updated => 视图更新就触发.不能知道本次更新是由于哪个数据变化导致的.具有响应式效果的数据变化,都触发updated.
watch => 数据变化就触发.监听哪个数据,就触发哪个方法. - 更新真实节点
数据变化 => 导致视图更新 (响应式)
数据变化 => 先更新虚拟节点 => diff算法判断 => 最后更新真实节点。- 原地更新.(标签不增删,不移动,直接修改内容或者属性)(更新前后是同一个标签) => 更新前后的tag和key完全一致.
- 替换更新.(会增删,移动元素)(新增,删除,移动) => tag或key有一个不一样.
- 什么时候原地更新?什么时候替换更新?
- 比较更新前后的虚拟节点.(同级比较)
- 如果同级的tag一致,并且key一样,则表示更新前后是同一个标签,使用原地更新策略.
- 如果同级的tag或者key有一个不一样,则表示更新前后不是同一个标签,使用替换更新策略.
4. 销毁期
destroyed => 组件销毁后的善后处理,例如停止定时器
组件销毁只是让数据不驱动视图更新了而已.组件实例还是存在的.
5.父子组件生命周期顺序
父beforeCreate
父created
父beforeMount
子beforeCreate
子created
子beforeMount
子mounted
父mounted
为什么顺序是这样的. => 函数执行顺序回答.父组件的视图编译就是一个函数从上往下执行.
能不能修改这个顺序.(4父4子) => 通过v-if实现.父组件挂载后再编译子组件.
三. nextTick
如何针对某个数据变化导致的视图更新写单独的逻辑?
vue的视图更新是异步的,数据变化不会马上导致视图更新.
nextTick的回调函数,会在视图更新后自动触发.只触发一次
一定是用来处理跟视图相关的逻辑.
const App = {
template: `
<div>
<button @click='fn'>修改str</button>
<ul ref='ul'>
<li v-for='d in count'>{{d}}</li>
</ul>
</div>
`,
data() {
return {
count: 0
}
},
methods: {
fn() {
// 数据变化会导致视图变化.视图变化完成之后,就会触发nextTick
this.count++;
// 这里只会在count变化导致的视图更新后触发.
this.$nextTick(() => {
let oUl = this.$refs.ul;
oUl.scrollTop = oUl.scrollHeight - oUl.clientHeight;
});
}
}
}
标签:触发,生命周期,28,更新,Vue5,虚拟,视图,组件,节点 来源: https://www.cnblogs.com/DarkCrow/p/15353495.html