资讯专栏INFORMATION COLUMN

【Vue源码探究二】从 $mount 讲起,一起探究Vue的渲染机制

LeanCloud / 1677人阅读

摘要:的构造函数将自动运行启动函数。我在阅读源码的过程中,发现源码余行,而和模板编译相关的代码,则约有行左右。这个是创建的方法,作为第一个参数传入。最后会返回一个节点。这个时候将赋值为这个节点,挂载完成

mount, 意思为挂载。可以理解为将vue实例(逻辑应用),挂靠在某个dom元素(载体)上的一个过程。

一、创建Vue实例时的渲染过程

上一篇文章我们讲到, 在创建一个vue实例的时候(var vm = new Vue(options))。Vue的构造函数将自动运行 this._init(启动函数)。启动函数的最后一步为initRender(vm),

// Vue.prototype._init
    ...
    initLifecycle(vm);
    initEvents(vm);
    callHook(vm, "beforeCreate");
    initState(vm);
    callHook(vm, "created");
    initRender(vm);

initRender中调用vm.$mount(vm.$options.el),将实例挂载到dom上,至此启动函数完成。

//initRender
  ...
  if (vm.$options.el) {
    vm.$mount(vm.$options.el);
  }

可以看出,vm.$mount为vue渲染的主要函数

二、Vue的渲染机制

上图,展示的是独立构建时的一个渲染流程图

模板字符串

//模板字符串
{{message}}

render函数

//render函数
function anonymous() {
with(this){return _h("div",{attrs:{"id":"app"}},["
  "+_s(message)+"
"])}
}

vnode

真实dom节点($el)

独立构建 与 运行时构建

我们先看一下官方文档 独立构建和运行时构建

这两个概念,我在初学的时候是一头雾水。现在对照着渲染的流程图,我们可以知道

独立构建:包含模板编译器
渲染过程: html字符串 → render函数 → vnode → 真实dom节点

运行时构建: 不包含模板编译器
渲染过程: render函数 → vnode → 真实dom节点

运行时构建通过砍掉模板编译器,让整个包少了30%(官方数据)。我在阅读源码的过程中,发现vue源码7000余行,而和模板编译相关的代码,则约有1000行左右。看起来确实是轻便了。这是在鼓励我们多用render函数吗?

三、$mount函数

上面我们说到,运行时构建的包,会比独立构建少一个模板编译器。在$mount函数上也不同

运行时构建的 $mount函数

而独立构建的 $mount函数,会先用一个临时变量mount保存上面的$mount方法

var mount = Vue$2.prototype.$mount;  //此处mount即为运行时版的 $mount

然后重写$mount函数,这时,调用$mount就会包括模板编译功能了

var mount = Vue$2.prototype.$mount;
Vue$2.prototype.$mount = function (el, hydrating) {
  ...省略代码(里面为模板编译器入口)...
  return mount.call(this, el, hydrating)
};

我们可以看到,不管独立构建还是运行时构建,都会调用 vm._mount方法我们来看看源码

Vue.prototype._mount = function(el, hydrating) {
    ...一些防止运行时的包,却用了template的报错代码...


    callHook(vm, "beforeMount");

    vm._watcher = new Watcher(vm, function () {
      vm._update(vm._render(), hydrating);
    }, noop);
    
    hydrating = false;

    if (vm.$vnode == null) {
      vm._isMounted = true;
      callHook(vm, "mounted");
    }
    return vm    
    
}

使用过的vue的人,都会很敏锐地发现, 在调用beforeMount生命周期,和mounted生命周期中间的关键代码为

鉴于大牛已经讲过很多次这里的数据监听了,我们只讲其中渲染部分

vm._update(vm._render(), hydrating);

vm._render函数返回一个vnode作为 vm._update的参数。 hydrating是与服务器渲染(SSR)相关的,浏览器端可以不用管。

vm._render (将render函数转化成vnode)

最核心代码为

var render = vm.$options.render
try{
  vnode = render.call(vm._renderProxy, vm.$createElement);
}catch{
  ...
}

此处,使用call方法, 将this指向 vm.renderProxy js功底差的同学要去补补知识了。
vm.renderProxy是个代理,代理vm,主要用来报错,如果render函数上使用了vm上没有的属性或方法,就会报错。
vm.$createElement 这个是创建vnode的方法,作为第一个参数传入。

render函数
这里的h即是, vm.$createElement ,便是在vm._render这个阶段被传入。

vm._update (将vnode生成真实dom节点)

最关键一句话为

 vm.$el = vm.__patch__(prevVnode, vnode);

vm.__patch__也是个大家伙,我之后会再去研究。
里面的方法,将新旧vnode使用 diff算法进行比对,找出要替换的地方,这样更新dom的性能会有较大优化。
最后会返回一个dom节点。
这个时候将vm.$el 赋值为这个dom节点,挂载完成!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83077.html

相关文章

  • Vue源码探究一】当我们引入Vue,我们引入了什么?

    摘要:源码版本构造器实例选项让我们用一段展示一下这三个概念其中的构造器实例实例名可以任意取,这里我们便于理解保持和文档一致选项即为传入构造器里的配置选项。其实构造器上也绑了不少好用的方法。 源码版本:2.0.5 构造器、实例、选项 让我们用一段demo展示一下这三个概念: //HTML {{ message }} //JS var vm = new Vue({ el: #app,...

    mengbo 评论0 收藏0
  • vue源码分析系列之响应式数据(一)

    摘要:代码初始化部分一个的时候做了什么当我们一个时,实际上执行了的构造函数,这个构造函数内部挂载了很多方法,可以在我的上一篇文章中看到。合并构造函数上挂载的与当前传入的非生产环境,包装实例本身,在后期渲染时候,做一些校验提示输出。 概述 在使用vue的时候,data,computed,watch是一些经常用到的概念,那么他们是怎么实现的呢,让我们从一个小demo开始分析一下它的流程。 dem...

    liujs 评论0 收藏0
  • Vue中父子组件生命周期执行顺序初探

    摘要:结论父子组件生命周期钩子的执行顺序遵循从外到内,然后再从内到外,不管嵌套几层深,也遵循这个规律。组件化的设计思路大抵相同,中父子组件生命周期钩子执行顺序,具体没做探究,但是值得一提的是父组件的也是晚于子组件执行的。 如今前端框架都流行组件化,页面元素都可以使用组件进行高度概括,那么处理组件之间的关系就如同处理页面架构一样重要。正确理解组件之间的关系,才能让代码按照我们与预料方式工作。最...

    Yumenokanata 评论0 收藏0
  • 用WEB技术栈开发NATIVE应用():WEEX 前端SDK原理详解

    摘要:依旧采取传统的开发技术栈进行开发,同时在终端的运行体验不输。首先来看下前端开发框架目前与构成了三大最流行的前端开发框架,具有组件化以及三大特性,还学习的,引入了状态管理模块。 摘要: WEEX依旧采取传统的web开发技术栈进行开发,同时app在终端的运行体验不输native app。其同时解决了开发效率、发版速度以及用户体验三个核心问题。那么WEEX是如何实现的?目前WEEX已经完全开...

    ls0609 评论0 收藏0
  • vue生命周期解析并通过表单理解MVVM(不仅理论,图文并茂)

    摘要:在前端页面中,把用纯对象表示,负责显示,两者做到了最大限度的分离。的显示与否和的布尔值有关,还是只关注数据的变化。两个组件的布尔值通过两个临近的按钮控制,初始值和的结果都是。组件的声明在组件上,则完全没有进入生命周期。 开始前说一说 吐槽 首先, 文章有谬误的地方, 请评论, 我会进行验证修改。谢谢。 vue真是个好东西,但vue的中文文档还有很大的改进空间,有点大杂烩的意思,对于怎么...

    silvertheo 评论0 收藏0

发表评论

0条评论

LeanCloud

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<