// public mount method
Vue.prototype.$mount = function (
el,
hydrating
) {
el = el && inBrowser ? query(el) : undefined;
return mountComponent(this, el, hydrating)
};
这里看到$mount的函数在Vue的原型链上,Vue的任何实例都可以直接调用这个方法
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
//Vue的实例调用$mount
new Vue({
render: h => h(App),
}).$mount('#app')
接下来我们来查看返回的函数mountComponent运行情况
function mountComponent (
vm,
el,
hydrating
) {
vm.$el = el;
if (!vm.$options.render) {
vm.$options.render = createEmptyVNode;
if (process.env.NODE_ENV !== 'production') {
/* istanbul ignore if */
if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
vm.$options.el || el) {
warn(
'You are using the runtime-only build of Vue where the template ' +
'compiler is not available. Either pre-compile the templates into ' +
'render functions, or use the compiler-included build.',
vm
);
} else {
warn(
'Failed to mount component: template or render function not defined.',
vm
);
}
}
}
// step 1 - vm.$options.render = true
callHook(vm, 'beforeMount');
var updateComponent;
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
updateComponent = function () {
var name = vm._name;
var id = vm._uid;
var startTag = "vue-perf-start:" + id;
var endTag = "vue-perf-end:" + id;
mark(startTag);
var vnode = vm._render();
mark(endTag);
measure(("vue " + name + " render"), startTag, endTag);
mark(startTag);
vm._update(vnode, hydrating);
mark(endTag);
measure(("vue " + name + " patch"), startTag, endTag);
};
} else {
// step 2 - config.performance = false
updateComponent = function () {
vm._update(vm._render(), hydrating);
};
}
// we set this to vm._watcher inside the watcher's constructor
// since the watcher's initial patch may call $forceUpdate (e.g. inside child
// component's mounted hook), which relies on vm._watcher being already defined
new Watcher(vm, updateComponent, noop, {
before: function before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate');
}
}
}, true /* isRenderWatcher */);
hydrating = false;
// manually mounted instance, call mounted on self
// mounted is called for render-created child components in its inserted hook
if (vm.$vnode == null) {
vm._isMounted = true;
callHook(vm, 'mounted');
}
return vm
}
$mount的使用
一、vm..$mount('#app')
new Vue({
render: h => h(App),
}).$mount('#app')
来源:
step1:this._init(options)
Vue.prototype._init = function (options) {
......
initRender(vm);
......
}
step2:initRender(vm);
function initRender (vm) {
......
// bind the createElement fn to this instance
// so that we get proper render context inside it.
// args order: tag, data, children, normalizationType, alwaysNormalize
// internal version is used by render functions compiled from templates
vm._c = function (a, b, c, d) { return createElement(vm, a, b, c, d, false); };
// normalization is always applied for the public version, used in
// user-written render functions.
vm.$createElement = function (a, b, c, d) { return createElement(vm, a, b, c, d, true); };
......
}
step3:initRender(vm);
function createComponent (
Ctor,
data,
context,
children,
tag
) {
......
// install component management hooks onto the placeholder node
installComponentHooks(data);
......
}
step3:installComponentHooks
function installComponentHooks (data) {
var hooks = data.hook || (data.hook = {});
for (var i = 0; i < hooksToMerge.length; i++) {
var key = hooksToMerge[i];
var existing = hooks[key];
var toMerge = componentVNodeHooks[key];
if (existing !== toMerge && !(existing && existing._merged)) {
hooks[key] = existing ? mergeHook$1(toMerge, existing) : toMerge;
}
}
}
step4:hooksToMerge
var hooksToMerge = Object.keys(componentVNodeHooks);
step5:componentVNodeHooks
// inline hooks to be invoked on component VNodes during patch
var componentVNodeHooks = {
init: function init (vnode, hydrating) {
if (
vnode.componentInstance &&
!vnode.componentInstance._isDestroyed &&
vnode.data.keepAlive
) {
// kept-alive components, treat as a patch
var mountedNode = vnode; // work around flow
componentVNodeHooks.prepatch(mountedNode, mountedNode);
} else {
//这里我们可以找到child,即是我们各个Vue实例,生成一个实例,执行一次$mount函数
var child = vnode.componentInstance = createComponentInstanceForVnode(
vnode,
activeInstance
);
//当生成Vue实例后可以$mount生成真正的dom
child.$mount(hydrating ? vnode.elm : undefined, hydrating);
}
},
......
二、增加Vue的option {el:'#app'}
new Vue({
el:'#app',
render: h => h(App),
})
实现方式是:我们可以看到vm.mount函数
Vue.prototype._init = function (options) {
......
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
}