vue2源码解析

253 阅读2分钟

vue2源码

初始化流程

entry-runtime-with-compiler.js

文件位置:src\platforms\web\entry-runtime-with-compiler.js 运行时+编译器入口文件 作用: 1.扩展$mount 2.render不存在会查找template或el选项 3.执行默认的挂载行为mount.call(this, el, hydrating)

runtime/index.js

文件位置:src\platforms\web\runtime\index.js 作用 1.安装平台补丁函数__patch__ 2.声明$mount方法

core/index.js

文件位置:src\core\index.js 作用 1.初始化全局api; 2.Vue.prototype.isServer3.Vue.prototype.isServer; 3.Vue.prototype.ssrContext;

  • initGlobalAPI

    文件位置:src\core\global-api\index.js 作用:初始化Vue常见的静态方法 1.Vue.util 2.Vue.set 3.Vue.delete 4.Vue.nextTick 5.Vue.observable ...

vue构造函数core\instance\index.js

文件位置:src\core\instance\index.js 作用: 1.声明vue构造函数 2.初始化势力属性和方法

  • initMixin

    文件位置:src\core\instance\init.js 作用: 1.vue核心初始化流程 2.如果设置了el,则直接调用el,则直接调用mount

    • 选项合并

      实现 1.initInternalComponent 2.mergeOptions

    • initLifecycle

      文件位置:src\core\instance\lifecycle.js 作用:初始化生命周期属性 1.vm.parent2.vm.parent 2.vm.root 3.vm.children4.vm.children 4.vm.refs ...

    • initEvents

      文件位置:src\core\instance\events.js 作用:初始化自定义事件

    • initRender

      文件位置:src\core\instance\render.js 作用:初始化渲染函数 1.vm.slots2.vm.slots 2.vm.scopedSlots 3.vm._c 4.vm.createElement5.createElement 5.attrs 6.$listeners

    • callHook(vm, 'beforeCreate')

      派发beforeCreate生命周期钩子

    • initInjections(vm)

      文件位置:src\core\instance\inject.js 作用:收集祖先组件传递的参数

    • initState(vm)

      文件位置:src\core\instance\state.js 作用:数据初始化

      • initProps

        作用:对props每一项做响应式

      • initMethods

        作用:methods方法代理到当前实例下vm

      • initData

        作用:data响应式处理函数

        • observe

          文件位置:src\core\observer\index.js 作用: 判断传入对象是否为响应式对象并返回“ob” 1.YES:直接返回; 2.NO:new Observer(value) 初始化创建;

          • new Observer(value)

            作用: 1.创建对象级 dep; 2.响应式对象上增加__ob__属性, 指向当前Ob; 3.数组原型覆盖; 4.区分传入对象类型,做不同响应式处理walk、observeArray;

            • arrayMethods(数组原型函数重写)

              文件位置:src\core\observer\array.js 作用:数组7个方法push,pop,shift,unshift,splice,sort,reverse 1.执行原有功能; 2.push unshift splice新增数据的响应式处理 3.变更通知ob.dep.notify()

            • observeArray(数组响应式)

              作用:遍历数据每一项执行observe做响应式

            • walk(对象响应式)

              作用:遍历对象的每一个属性做响应式处理

              • defineReactive

                作用 1.创建属性级 dep; 2.递归子对象 3.get拦截 4.set拦截

                • get

                  • 当前属性的依赖收集dep.depend()

                    作用:当前属性dep和watcher相互创建引用关啊

                  • 子对象的依赖收集childOb.dep.depend()

                    作用:子对象的ob内部的dep也要和watcher关联

                • set

                  • 新增值的响应式observe(newVal)
                  • 变更通知dep.notify()
      • initComputed

        作用:初始化计算属性,产生user watcher

        • defineComputed
      • initWatch

        作用:初始化监听对象,产生user watcher

        • createWatcher
    • initProvide(vm)

      文件位置:src\core\instance\inject.js 作用:处理provide

    • callHook(vm, 'created')

      派发created生命周期钩子

  • stateMixin

  • eventsMixin

  • lifecycleMixin

  • renderMixin

挂载$mount

mountComponent

  • callHook(vm, 'beforeMount')

  • new Watcher(vm, updateComponent,...)

    作用:初始化订阅者Wather(render)

    • this.get()

      文件位置:src\core\observer\watcher.js 作用:this.getter

      • updateComponent

        文件位置:src\core\instance\lifecycle.js 作用: 1.vm._render()获取最新的vnode,触发依赖收集 2.执行vm._update()

        • _update()

          文件位置:src\core\instance\lifecycle.js 作用 1.初始化__patch__ 传入oldVnode为vm.$el; 2.更新__patch__ 传入oldVnode为prevVnode;

          • patch

            文件位置:src\core\vdom\patch.js

            • 新vnode不存在-删除

            • 老vnode不存在-新增

            • patchVnode

              • 1.元素属性更新

              • 2.新老vnode都存在子节点

                • updateChildren

                  作用:diff核心代码(同层比较深度优先) 1.四种猜想:首首 尾尾 首尾 尾首 2.循环查找新节点在老节点的位置 3.扫尾工作 (sameVnode 判断是否为同一节点 体现key的重要性)

                  • 1.四种猜想:首首 尾尾 首尾 尾首(比较)

                  • 2.循环查找新节点在老节点的位置

                    • 不存在创建createElm

                    • 存在

                      • 相同节点patchVnode & insertBefore移位
                      • key相同节点标签不同创建 createElm
                  • 3.扫尾:老数组有剩下的批量删除removeVnodes

                  • 3.扫尾:新数组有剩下的批量新增addVnodes

              • 3.老节点undef & 新节点def

                • addVnodes创建元素
              • 4.老节点def & 新文本undef

                • removeVnodes移除元素
              • 5.老节点文本 & 新节点无文本

                • setTextContent文本置空
              • 6.新老节点都是文本

                • setTextContent文本更新
            • 初始化

              • createElm

                作用:转换vnode为真实dom树

              • 移除模板的宿主元素removeVnodes

异步更新

dep.notify()

文件位置:src\core\observer\index.js

  • 遍历执行Watcher.update()

    文件位置:src\core\observer\watcher.js

    • queueWatcher()

      文件位置:src\core\observer\scheduler.js 作用:Watcher入队

      • nextTick

        文件位置:src\core\util\next-tick.js 作用 1.flushSchedulerQueue传入到callbacks数组 2.用户传入的cb函数传入到callbacks数组 3.异步启动

        • timerFunc

          异步策略:Promise 》MutationObserver 》setImmediate 》 setTimeout

          • flushCallbacks

            作用:遍历执行callback存放的执行函数

            • flushSchedulerQueue

              文件位置:src\core\observer\scheduler.js 作用 1.watcher的队列升序 2.以此执行

              • callHook(vm, 'beforeUpdate')

              • watcher.run()

                作用:执行组件更新函数

              • callHook(vm, 'updated')