美文网首页
(四)Vue-渲染过程

(四)Vue-渲染过程

作者: JerrySi | 来源:发表于2022-02-28 23:11 被阅读0次

    Vue 的不同构建版本

    完整版:同时包含编译器和运行时的版本。
    编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码,体积大、效率低。
    运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码,体积小(小大约 30%)、效率高。基本上就是除去编译器的代码。

    UMD:UMD 版本通用的模块版本,支持多种模块方式。 vue.js 默认文件就是运行时 + 编译器的UMD 版本。
    CommonJS(cjs):CommonJS 版本用来配合老的打包工具比如 Browserify 或 webpack 1。
    ES Module:从 2.6 开始 Vue 会提供两个 ES Modules (ESM) 构建文件,为现代打包工具提供的版本。

    • ESM 格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行“tree-shaking”并将用不到的代码排除出最终的包。
    • ES6 模块与 CommonJS 模块的差异

    基于Vue 2.6版本

    入口

    • el 不能是 body 或者 html 标签
    • 如果没有 render,把 template 转换成 render 函数
    • 如果有 render 方法,直接调用 mount 挂载 DOM
    // 1. el 不能是 body 或者 html 
    if (el === document.body || el === document.documentElement) {   
          process.env.NODE_ENV !== 'production' && warn( `Do not mount Vue to 
               <html> or <body> - mount to normal elements instead.` )
          return this 
    }
    
    const options = this.$options if (!options.render) { 
        // 2. 把 template/el 转换成 render 函数 …… 
    }
        
    // 3. 调用 mount 方法,挂载 DOM 
    return mount.call(this, el, hydrating)
    

    初始化流程

    1. src/platform/web/entry-runtime-with-compiler.js 中引用了 './runtime/index'
    2. src/platform/web/runtime/index.js
    • 设置 Vue.config
    • 设置平台相关的指令和组件
      指令 v-model、v-show
      组件 transition、transition-group
    • 设置平台相关的 patch 方法(打补丁方法,对比新旧的 VNode)
    • 设置 $mount 方法,挂载 DOM
    // install platform runtime directives & components extend(Vue.options.directives, platformDirectives) extend(Vue.options.components, platformComponents) 
    
    // install platform patch function 
    Vue.prototype.__patch__ = inBrowser ? patch : noop
    
     // public mount method Vue.prototype.$mount = function ( 
        el?: string | Element, 
        hydrating?: boolean ): Component { 
        el = el && inBrowser ? query(el) : undefined 
        return mountComponent(this, el, hydrating) 
    }
    
    1. src/platform/web/runtime/index.js 中引用了 'core/index'
    2. src/core/index.js
    • 定义了 Vue 的静态方法
    • initGlobalAPI(Vue)
    1. src/core/index.js 中引用了 './instance/index'
    2. src/core/instance/index.js
    • 定义了 Vue 的构造函数
    // 此处不用 class 的原因是因为方便,后续给 Vue 实例混入实例成员 
    function Vue (options) { 
        if (process.env.NODE_ENV !== 'production' && 
          !(this instanceof Vue) ) {
              warn('Vue is a constructor and should be called with the `new` keyword') 
        }
    
        // 调用 _init() 方法 
        this._init(options) 
    }
    
    // 注册 vm 的 _init() 方法,初始化 
    vm initMixin(Vue) 
    // 注册 vm 的 $data/$props/$set/$delete/$watch 
    stateMixin(Vue) 
    // 初始化事件相关方法 
    // $on/$once/$off/$emit 
    eventsMixin(Vue) 
    // 初始化生命周期相关的混入方法 
    // _update/$forceUpdate/$destroy 
    lifecycleMixin(Vue) 
    // 混入 render 
    // $nextTick/_render 
    renderMixin(Vue)
    

    导出Vue涉及的四个模块

    1. src/platforms/web/entry-runtime-with-compiler.js
    • web 平台相关的入口
    • 重写了平台相关的 $mount() 方法
    • 注册了 Vue.compile() 方法,传递一个 HTML 字符串返回 render 函数
    1. src/platforms/web/runtime/index.js
    • web 平台相关
    • 注册和平台相关的全局指令:v-model、v-show
    • 注册和平台相关的全局组件: v-transition、v-transition-group
    • 全局方法:
      patch:把虚拟 DOM 转换成真实 DOM
      $mount:挂载方法
    1. src/core/index.js
    • 与平台无关
    • 设置了 Vue 的静态方法,initGlobalAPI(Vue)
    1. src/core/instance/index.js
    • 与平台无关
    • 定义了构造函数,调用了 this._init(options) 方法
    • 给 Vue 中混入了常用的实例成员

    首次渲染过程

    1. 实例化Vue对象的时候。会调用this._init()进行一些初始化, 同时会调用vm.$mount函数。

    这里的vm.$mount函数 首先调用src/platforms/web/entry-runtime-with-compiler.js 里面重写的$mount() 方法。

    1. 重写的vm.$mount函数: 通过Vue.compile() 方法,返回 render 和 staticRenderFns 函数, 存储在$options里面。 然后调用原始的vm.$mount函数。
    • 这里的render:如果用户定义,返回用户定义的; 否则返回模板生成的。
    • 原始的vm.$mount函数 是src/platforms/web/runtime/index.js 里面定义的
    • src/platforms/web/runtime/index.js里面同时定义了vm.patch方法把虚拟Dom转成真实Dom
    1. 原始的vm.$mount函数:调用 mountComponent方法。
      mountComponent定义在/src/core/instance/lifecycle.js
    2. mountComponent方法主要做了4件事:
    • 触发beforeMount钩子
    • 定义updateComponent方法, 注意这里只是定义, 触发是Watcher触发的。
    • 创建Watcher实例, 把updateComponent方法作为参数传入。
    • 触发mounted钩子
      4.1 updateComponent方法比较重要, 主要做了2件事:
      vm._rander渲染虚拟Dom。
      vm._rander其实就是调用第二步$options中的render方法
      vm._update更新,把虚拟Dom转成真实Dom 。
      vm._update其实就是调用src/platforms/web/runtime/index.js中的定义的vm.__patch__方法, 同时记录vm.$el
      4.2 Watcher构造方法
      会把传入的updateComponent参数赋值给this.getter。
      this.get()方法里面调用this.getter。
      立即调用this.get(), 进而触发渲染。

    Demo

    相关文章

      网友评论

          本文标题:(四)Vue-渲染过程

          本文链接:https://www.haomeiwen.com/subject/uuhrrrtx.html