Vue源码解析-Vue和实例对象
2020-03-05 本文已影响0人
kruz
先看一下源码中关于Vue函数的定义(稍稍简化),摘自Vue 2.6.11。
function Vue (options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options); // 调用Vue.prototype._init函数, this指向的就是Vue实例对象了
}
//调用一系列方法
initMixin(Vue); // 初始化,调用initMixin函数,传入Vue构造函数
stateMixin(Vue);
eventsMixin(Vue);
lifecycleMixin(Vue);
renderMixin(Vue);
function initMixin (Vue) {
Vue.prototype._init = function (options) {
var vm = this; // vm被赋值为实例对象
vm._uid = uid$3++; // 当触发init方法,新建Vue实例时(当渲染组件时也会触发)uid都会递增
// 加入标志防止该对象对observer监听
vm._isVue = true;
// 合并options
if (options && options._isComponent) { // 当是组件时
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent(vm, options);
} else { // 当不是组件时
// 将合并后的options赋值給实例对象的$options
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
initProxy(vm);
// 实例对象的_self指向自己, 暴露出去
// 各种初始化
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook(vm, 'beforeCreate'); // 触发beforeCreate生命周期函数
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created'); // 触发created生命周期函数
// 挂载el
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};
}
看看
Vue就是一个函数,当然可以把它理解为构造函数和类,她只能用new 来生成实例对象。
我们平常使用引入Vue的方式就是:
var vm = new Vue({
el: '#app',
data: {
showA: false
},
beforeCreate(){
},
created(){
},
mounted(){
},
methods: {
}
});
// 可以打印出如下的数据
console.log(vm instanceof Vue); // true;
console.log(vm._self === vm); // true;
console.log(vm._isVue); // true;
console.log(vm._uid ); // 0; // 只有一个实例且没有组件就是0
console.log(vm.$options); // 生成后的options
_init函数最重要的两个部分就是:
1.初始化各种状态,然后调用
beforeCreated
和created
生命周期函数。
2.合并options生成 $options, 然后挂载。
看看$options的由来:
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
resolveConstructorOptions函数生成的对象含有:components
,directives
, filters
,
然后再进行合并:
最后得出的$options,含有:
{
components: {}
directives: {}
filters: {}
_base: ƒ Vue(options)
el: "#app"
data: ƒ mergedInstanceDataFn()
mounted: [ƒ]
methods: { beforeEnter: ƒ, enter: ƒ, leave: ƒ, changeShow: ƒ}
render: ƒ anonymous( )
staticRenderFns: []
}
然后去调用$amount函数,执行挂载。