前言
- 一个组件渲染到页面,修改
data
触发更新(数据驱动视图) - 其背后原理是什么,需要掌握哪些点
- 考察对流程了解的全面程度
回顾三大核心知识点
-
响应式:监听
data
属性getter
、setter
(包括数组) -
模板编译:模板到
render
函数,再到vnode
-
vdom:两种用法
patch(elem,vnode)
首次渲染vnode
到container
上patch(vnode、newVnode)
新的vnode
去更新旧的vnode
-
搞定这三点核心原理,
vue
原理不是问题
组件渲染更新过程
-
1. 初次渲染过程
-
解析模板为
render
函数(或在开发环境已经完成vue-loader
模板编译) -
触发响应式,监听
data
属性getter
、setter
-
执行
render
函数(执行render
函数过程中,会获取data
的属性触发getter
),生成vnode
,在执行patch(elem,vnode)
elem
组件对应的dom
节点const template = <p>{message}</p>
- 编译为
render
函数with(this){return _c('p', [_v(_s(message))])}
this
就是vm
的实例,message
等变量会从vm
上读取,触发getter
进行依赖收集
export default { data() { return { message: 'hello' // render函数执行过程中会获取message变量值,触发getter } } }
-
-
2. 更新过程
- 修改
data
,触发setter
(此前在getter
中已被监听) - 重新执行
render
函数,生成newVnode
- 在调用
patch(oldVnode, newVnode)
算出最小差异,进行更新
- 修改
-
3. 完成流程图
异步渲染
- 汇总
data
的修改,一次更新视图 - 减少
DOM
操作次数,提高性能
methods: {
addItem() {
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
// 1.页面渲染是异步的,$nextTick待渲染完在回调
// 2.页面渲染时会将data的修改做整合,多次data修改也只会渲染一次
this.$nextTick(()=>{
const ulElem = this.$refs.ul
console.log(ulElem.childNotes.length)
})
}
}
总结
- 渲染和响应式的关系
- 渲染和模板编译的关系
- 渲染和
vdom
的关系