Vue模板挂载到页面原理分析

Vue模板挂载到页面可以分为两大部分initmount

1. init

Vue.prototype._init = function() {
    // 初始化选项,computed data
    // 初始化实例,给实例绑定方法
    // 触发beforeCreated created钩子
}

2. mount

上面介绍的_init方法中,会有一个挂在到dom的方法

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

不是所有的Vue实例在初始化的时候都会去执行`$mount`方法去挂载DOM,比如component

```js
Vue.prototype.$mount = function(el) {    
    return mountComponent(this, query(el))
};
function mountComponent(vm, el) {    
    new Watcher(vm, function() {
        // 新建watcher,并且设置一个更新函数,当数据发生变化时,会重新执行这个更新函数
        vm._update(vm._render());
    })    
    return vm
}

function Watcher(vm, expOrFn) {    
    this.getter = expOrFn;    
    this.get();
}
Watcher.prototype.get = function() {
    value = this.getter(vm);
}

vm._render会解析得到一个渲染函数,渲染函数执行完全返回一个模板对应的vnode

Vue.prototype._render = function() {
    vnode = render();    
    return vnode
}

vm._update这个函数的作用是对比vnode, 挂载更新DOM

  1. 如果存在旧DOM,那么会对比旧VNode和刚刚传入的新的VNode,不断patch得到最小变化单位,从而更新这部分DOM
  2. 如果不存在旧 vnode,那么就直接把 vnode 转换为 dom 挂载到页面。其中,生成DOM 和 挂载DOM 用到的方法是 createElm
function createElm(vnode, parentElm, refElm) {  
    var children = vnode.children;    
    var tag = vnode.tag;
    vnode.elm = document.createElement(tag);   
    // 不断递归遍历子节点
    createChildren(vnode, children);    
    // 插入DOM 节点
    insert(parentElm, vnode.elm, refElm);
}
function createChildren(vnode, children) {    
    if (Array.isArray(children)) {        
        for (var i = 0; i < children.length; ++i) {
            createElm(children[i], vnode.elm, null);
        }
    }
}
function insert(parent, elm, ref) { 
    if (parent) {   
        // 如果存在兄弟节点,就查到兄弟前面
        if (ref) {       
            // 兄弟节点的父节点和 本节点父节点相同
            if (ref.parentNode === parent) {
                parent.insertBefore(elm, ref);
            }
        } 
        // 如果没有兄弟节点,就直接查到父节点最后
        else {
            parent.appendChild(elm);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值