Vue源码流程总结

1. Vue的初始化过程

1. 初始化生命周期

2. 初始化事件系统

3. 初始化state,依次处理props, methods, data, computed ...

export function initState(vm: Component) {
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)              
  if (opts.methods) initMethods(vm, opts.methods)        
  if (opts.data) initData(vm)                            
  if (opts.computed) initComputed(vm, opts.computed)     
  if (opts.watch) initWatch(vm, opts.watch)              
  }
}
4. 开始渲染 _mount() => _render() => 返回vdom => _update() => _patch() 更新dom

2. Vue数据响应式原理

initData 初始化用户数据

observe 将数据进行观测

new Observer 定义观测对象

this.walk(value) 循环处理对象的所有key

defineReactive  将对象的指定key定位为响应式

Object.defineProperty 在get和set方法种定义响应式,在get方法种用 Dep.depend 进行依赖收集
在set方法中用 dep.notify 进行依赖更新通知

3. Vue数组变化检测
 
对数组类型的数据,进行方法重写,将原数组方法替换为自定义的同名方法,在自定义方法中调用原方法取值,并进行依赖更新通知。
依然是使用 dep.notify 方法
 
initData 初始化用户数据
 
observe 观测用户数据
 
new Observer 定义观测对象
 
protoAugment 将数组的原型方法指向重写的原型
 
重写数组的原型方法,并添加变更通知
 
深度观测数组中的每一项引用类型
 
4. Vue异步渲染步骤
// src/core/observer/dep.js
let uid = 0            // Dep实例的id,为了方便去重

export default class Dep {
  static target: ?Watcher           // 当前是谁在进行依赖的收集
  id: number
  subs: Array<Watcher>              // 观察者集合
 
  constructor() {
    this.id = uid++                             // Dep实例的id,为了方便去重
    this.subs = []                              // 存储收集器中需要通知的Watcher
  }

  addSub(sub: Watcher) { ... }  /* 添加一个观察者对象 */
  removeSub(sub: Watcher) { ... }  /* 移除一个观察者对象 */
  depend() { ... }  /* 依赖收集,当存在Dep.target的时候把自己添加观察者的依赖中 */
  notify() { ... }  /* 通知所有订阅者 */
}

const targetStack = []           // watcher栈

export function pushTarget(_target: ?Watcher) { ... }  /* 将watcher观察者实例设置给Dep.target,用以依赖收集。同时将该实例存入target栈中 */
export function popTarget() { ... }  /* 将观察者实例从target栈中取出并设置给Dep.target */
pushTaget和popTarget是和Dep类同级的方法,直接暴露给其他类使用
dep.notify() dep通知更新
 
subs[i].update() dep中的watcher调用update方法
 
queueWatcher 将watcher加入到队列中
 
nextTick(flushSchedulerQueue) 在下一个tick,flush队列,执行所有的watcher方法
 
5. nextTick方法实现原理
 
nextTick(cb) nextTick方法传入回调
 
callbacks.push(cb) 数组存储所有回调
 
timerFunc 在timerFunc中调用回调,timerFunc是用microTask模拟的,例如Promise.then, MutationObserver,setImmedate,setTimeout等
 
返回Promise 可以执行then方法
 
6. Vue的computed实现过程
 
initComputed
 
new Watcher
 
defineComputed
 
createComputedGetter 在此方法中进行依赖收集,和依赖计算,即执行watcher.evaluate方法
 
用户取值 dirty = false 使用缓存,返回上次结果,dirty = true watcher.evaluate(),重新计算结果
 
7. Vue的响应式更新过程
 
model更新 set方法 -> 触发Dep.notify -> Dep的subs中的Watcher -> Watcher调用update -> queueWatcher -> nextTick -> flushQueueWatcher -> 生成新的Vnode -> 新VNode 与 老VNode 进行diff -> patch 将差异更新到视图
 
diff是patch过程的核心。diff算法有2个显著特点:
 
1. 只会同级进行比较,不会垮层级比较
2. 在diff列表过程中,循环从两边向中间收拢
 
 

原文地址:https://www.cnblogs.com/mengff/p/13553754.html