zoukankan      html  css  js  c++  java
  • 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列表过程中,循环从两边向中间收拢
     
     

  • 相关阅读:
    结合P2P软件使用Ansible分发大文件
    Centos7 上安装 FastDFS
    go在centos配置以及go mod配置
    代理
    笔记本安装ubuntu18.08,解决过程中出现的各种问题
    CentOS7设置自定义开机启动脚本,添加自定义系统服务
    gitlab忘记密码找回
    zabbix配置短信报警
    将博客搬至CSDN
    RT-Thread-stm32f769-qspi-flash移植
  • 原文地址:https://www.cnblogs.com/mengff/p/13553754.html
Copyright © 2011-2022 走看看