Vue2:Vue的加载流程和IDFF

vue加载流程

1.每一个组件在加载时都会调用vue内部的render函数来把这个组件的tamplate选项的模板解析为一个JS对象

这个对象跟DOM节点对象"长得一模一样",就是为了后来的渲染

Vue.prototype._init = function (options?: Object) {
   initLifecycle(vm) //1.初始化生命周期的函数
   initEvents(vm) //初始化事件
   initRender(vm)//生成vnode的模板
   callHook(vm, 'beforeCreate')//触发beforeCreate钩子
   initInjections(vm) //接受提供者提供的数据
   initState(vm)//初始化状态:具体过程在下面函数中--劫持
   initProvide(vm) //给别人提供数据
   callHook(vm, 'created')//触发created钩子
 }
 
 export function initState (vm: Component) {
   vm._watchers = []
   const opts = vm.$options
   if (opts.props) initProps(vm, opts.props) //有属性就初始化属性
   if (opts.methods) initMethods(vm, opts.methods)//有方法就初始化方法
   if (opts.data) {//有数据源就初始化数据源
     initData(vm)
   } else {
     observe(vm._data = {}, true /* asRootData */)//没有就监听自带的数据源
   }
   if (opts.computed) initComputed(vm, opts.computed)//有计算属性就初始化计算属性
   if (opts.watch && opts.watch !== nativeWatch) {
     initWatch(vm, opts.watch)//对属性监听
   }
 }
 //源码分析的结果:属性props>方法methods>数据源data>计算属性computed>对属性监听watch

打包-运行-挂载-每个组件生成的过程{初始化生命周期函数  render执行,把模板字符串翻译成VNode  数据劫持,观测watcher  数据替换  挂载}

如果数据源变了-通知订阅者watcher-异步更新页面-patch函数执行-DIFF-同层比较并打补丁-比较完毕再比较下一层

sameVNode  patchVNode  UpdataChildren-patchVNode

DIFF算法

什么是DIFF

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文 档当中

当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(diff),记录两棵树差异

把第二棵树所记录的差异应用到第一棵树所构建的真正的DOM树上(patch),视图就更新了

 

 

DIFF算法的过程

当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁

通过sameVnode进行判断,相同则调用patchVnode方法

patchVnode做了以下操作:

1、找到对应的真实dom,称为el

2、如果都有都有文本节点且不相等,将el文本节点设置为Vnode的文本节点

3、如果oldVnode有子节点而VNode没有,则删除el子节点

4、如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el

5、如果两者都有子节点,则执行updateChildren函数比较子节点

6、updateChildren主要做了以下操作:

(1)设置新旧VNode的头尾指针

(2)新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程、调用createElem创建一个新节点,从哈希表寻找 key一致的VNode 节点再分情况操作

 

 

Vue.prototype._init = function (options?: Object) {   initLifecycle(vm) //1.初始化生命周期的函数   initEvents(vm) //初始化事件   initRender(vm)//生成vnode的模板   callHook(vm, 'beforeCreate')//触发beforeCreate钩子   initInjections(vm) //接受提供者提供的数据   initState(vm)//初始化状态:具体过程在下面函数中--劫持   initProvide(vm) //给别人提供数据   callHook(vm, 'created')//触发created钩子 }  export function initState (vm: Component) {   vm._watchers = []   const opts = vm.$options   if (opts.props) initProps(vm, opts.props) //有属性就初始化属性   if (opts.methods) initMethods(vm, opts.methods)//有方法就初始化方法   if (opts.data) {//有数据源就初始化数据源     initData(vm)   } else {     observe(vm._data = {}, true /* asRootData */)//没有就监听自带的数据源   }   if (opts.computed) initComputed(vm, opts.computed)//有计算属性就初始化计算属性   if (opts.watch && opts.watch !== nativeWatch) {     initWatch(vm, opts.watch)//对属性监听   } } //源码分析的结果:属性props>方法methods>数据源data>计算属性computed>对属性监听watch
 
posted on 2022-09-08 09:47  香香鲲  阅读(404)  评论(0编辑  收藏  举报