• vue源码学习实例挂载的实现


    Vue实例挂载的实现

    Vue中我们是通过$mount实例方法去挂载vm的,$mount方法在多个文件中都有定义,如src/platform/web/entry-runtime-with-compiler.js、src/platform/web/runtime/index.js、src/platform/weex/runtime/index.js。因为$mount这个方法的实现是和平台、构建方式都相关的。接下来我们重点分析带compiler版本的$mount实现,因为抛开webpack的vue-loader,我们在纯前端浏览器环境分析Vue的工作原理,有助于我们对原理的理解深入。

    如果用一句话概括挂载的过程,可以描述为挂载组件,将渲染函数生成虚拟DOM,更新视图的时候,将虚拟DOM渲染成为真正的DOM

    详细的过程是,首先确定挂载的DOM元素,且必须保证该元素不能为html,body这类根节点,判断选项中是否有render这个属性(如果不在运行编译时候,则在选项时,需要传递render渲染函数)。当有render这个属性时,默认我们使用runtime-only版本,从而跳过模板编译阶段,调用真正挂载函数$mount。另一方面,当我们传递是templa模板时(即在不使用外置编译器的情况下,我们将使用runtime+compiler的版本),Vue源码将首先进入编译阶段。该阶段的核心是两步,一个是把模板解析成抽象语法树,也就四我们常听到的AST,第二个是根据给定的AST生成目标平台所需要的代码,在浏览器端是前面提到的render函数。完成模板编译后,同样会进入$mount挂载阶段。真正挂载的过程,执行的是mountComponent方法,改函数的核心是实例化一个渲染watcher,具体watcher的内容,这里先不说明。我们只要知道渲染watcher的作用,一个初始化的时候会执行回调函数,另一个是当vm实例中检测的数据发生变化的时候执行回调函数。而这个回调函数就是updateComponent,这个方法会通过vm._render生成虚拟DOM,并最终通过vm.update将虚拟DOM转化为真正的DOM。
    往下,我们从代码的角度出发,了解一下挂载的实现思路,下面值提取mount骨架代码说明。

    // 内部真正实现挂载的方法
    Vue.prototype.$mount = funtion (el, hydrating) {
      el = el && inBrowser? query(el) :undefined
      // 调用mountComponent方法挂载
      return mountComponent(this, el, hydrating)
    }
    
    // 缓存了原型上的$mount方法
    var mount = Vue.prototype.$mount
    // 重新定义$mount,为包含编译器和不包含编译器版本提供不同的封装,最终调用的是缓存原型上的$mount方法
    Vue.prototype.$mount = function (el, hydrating) {
      // 获取挂载元素
      el = el && query(el)
      // 挂载元素不能为根节点
      if(el === document.body || el === document.documentElement) {
     "Do not mount Vue to <html> or <body> - mount to normal elements instead."
     );
     return this
    }
     var options = this.$options;
     // 需要编译 or 不需要编译
     if (!options.render) {
     ···
     // 使用内部编译器编译模板
     }
     // 最终调用缓存的$mount方法
     return mount.call(this, el, hydrating)
    }
    // mountComponent方法思路
    function mountComponent(vm, el, hydrating) {
     // 定义updateComponent方法,在watch回调时调用。
     updateComponent = function () {
     // render函数渲染成虚拟DOM, 虚拟DOM渲染成真实的DOM
     vm._update(vm._render(), hydrating);
     };
     // 实例化渲染watcher
     new Watcher(vm, updateComponent, noop, {})
    }
    
  • 相关阅读:
    junit测试时,出现java.lang.IllegalStateException: Failed to load ApplicationContext
    Mybatis 3 返回布尔值,需要注意的地方
    mybatis sql in 查询
    在HTML中如何隐藏某段文字具体该怎么实现
    SpringMVC存取Session的两种方法
    spring mvc 使用session
    mybatis入门例子
    Android自定义GifView显示gif动画
    [wxWidgets]_[0基础]_[经常更新进度条程序]
    ASP.NET验证控件
  • 原文地址:https://www.cnblogs.com/dehenliu/p/16069448.html
Copyright © 2020-2023  润新知