美文网首页
vue源码解读--mount实例挂载的实现

vue源码解读--mount实例挂载的实现

作者: 习惯水文的前端苏 | 来源:发表于2020-12-02 21:42 被阅读0次

目录导航

上一节我们通过分析找到了vue的入口文件src/core/instance/index.js

当执行import vue时,将会执行this._init方法,该方法在初始化时定义在initMixin中

该方法接收一个options,即new vue时传递的对象,形如

new Vue({

    el:"#app",

    data(){

        return{

            msg:"hello"

        }

    }

})

I-使用vm缓存this,即vue

II-对options进行合并

III-通过initState调用,如果data存在,则调用initData()对data进行处理

        首先:获取定义的data,即实例化时传递的data函数

        其次:对data函数中的this指向进行修正,使其指向vue

        最后:确保在data中定义的属性msg未作为methods或props存在

    IV-向el指定的元素上挂载vue,并转化data

        vm.$mount是在Vue上挂载的方法,这在import Vue的时候已经被准备,打开entry-runtime-with-compiler.js

        可以发现,在该文件引入了$mount同时又新建了一个$mount,那么为什么要重复定义呢?通过debugger,我发现我当前的代码并没有走缓存的那一个mount,而是直接走到了下边。于是我打算看看缓存的mount到底做了什么

        如果是浏览器环境,则调用query方法

该方法调用原生dom API获取dom对象,即document.querySelector('#app'),也就是拿到了我们在根文件index.html中定义的id为app的div元素

接着执行mountComponent方法

首先判断是否定义了render函数,接着判断templete是否存在,然后就开始报警告

 我们知道vue是支持多种书写格式的,既可以使用render函数,也可以使用模板,而这里却是只允许render,并紧接着抛出了runtime-only的警告

 我恍然大悟,于是打开小窗口,vue init webpack test

也就是说,这两个$mount分别服务于两个版本的vuejs!!!

我在初始化项目时使用的是runtime+compiler版本,因此我着重看当前文件创建的mount方法

从框红的位置可以看出,vuejs不允许将html或者body作为根组件,并且对render进行了特别处理。那么问题有二:为什么必须定义一个空div作为根组件?;为什么偏偏要处理render?

展开if(!options.render)

    I-获取根组件<div id="app"></div>

    II-向options上挂载render方法

    III-执行缓存的mount方法,再次进入mountComponent方法,此时options上存在render函数,因此不会在报warn

performance是与性能相关的需要在vue配置文件中开启的,因此代码会走向else逻辑,定义一个updateComponent函数,该函数在实例化Watcher时被调用,其中vm._render()负责生成一个虚拟dom,并交由vm._update进行对比更新后生成一个真实dom

那么render到底如何生产vnode呢?(render函数

update又是如何将vnode更新为dom呢?(update

相关文章

网友评论

      本文标题:vue源码解读--mount实例挂载的实现

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