我们之前就说过vue是核心源码都是存放在src目录下面,接下来我们就看看src/core/index.js文件做了什么操作。
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
initGlobalAPI(Vue)
......为了不增大篇幅,省略部分代码(大家可自行查看)
export default Vue
我们可以看看这里调用了一个initGlobalAPI(Vue) 方法,并且传入了一个vue对象作为参数,我们一步一步来,先看一下vue对象的来源文件(src/core/instance/index.js)。
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
可以看到定义了一个简单的函数Vue,并且调用了_init函数。至于_init在哪里定义的我们接下来再看。
接下来可以清楚的看到调用了如下5个函数:
initMixin(Vue)// 初始化_init函数
stateMixin(Vue) // 处理数据 ( “$data”、“$props”)
eventsMixin(Vue) // 挂载内部事件
lifecycleMixin(Vue) // 挂载内部生命周期
renderMixin(Vue) // 挂载内部渲染所需的方法
initMixin(Vue)
我们先找到src/core/instance/init.js文件。
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options?: Object) {
......为了不增大篇幅,省略部分代码(大家可自行查看)
}
}
可以看到这个函数就是给Vue的原型对象上面注册了一个“_init”方法,其他什么都没干了。_init具体操作我们后面会再分析,现在先放过他。
stateMixin(Vue)
export function stateMixin (Vue: Class<Component>) {
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
const dataDef = {}
dataDef.get = function () { return this._data }
const propsDef = {}
propsDef.get = function () { return this._props }
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
Vue.prototype.$set = set
Vue.prototype.$delete = del
Vue.prototype.$watch = function (
expOrFn: string | Function,
cb: any,
options?: Object
): Function {
const vm: Component = this
if (isPlainObject(cb)) {
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {}
options.user = true
const watcher = new Watcher(vm, expOrFn, cb, options)
if (options.immediate) {
try {
cb.call(vm, watcher.value)
} catch (error) {
handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`)
}
}
return function unwatchFn () {
watcher.teardown()
}
}
}
可以看到上面对“$data”、“$props”属性都做了拦截操作,如果是开发环境对其进行赋值操作的话,都会引发一个“warn”的警告,代码如下:
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
最后在vue的“prototype”原型对象上面挂载了三个属性 “ $set”、“$delete”、“$watch”,我们在后面的会对他们进行分析。
eventsMixin(Vue)
这个函数主要是在vue的“prototype”原型对象上面挂载了几个自定义事件“$on”、“$once”、“$off”、“$emit”,对于这几个函数的用法大家都清楚了,我们后面会做详细的分析。
lifecycleMixin(Vue)
这个函数主要是在vue的“prototype”原型对象上面挂载了一些内部使用的生命周期函数“_update”、“$forceUpdate”、“$destroy”。一般以"$"开头或者以 _下划线开头的话,都是vue内部使用的。
renderMixin(Vue)
export function renderMixin (Vue: Class<Component>) {
installRenderHelpers(Vue.prototype)
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this)
}
Vue.prototype._render = function (): VNode {
......为了不增大篇幅,省略部分代码(大家可自行查看)
}
}
可以看到这个函数主要做了三件事情。
1、挂载一些实用的函数(installRenderHelpers(Vue.prototype)
2、在vue的“prototype”原型对象上面挂载“$nextTick”属性
3、在vue的“prototype”原型对象上面挂载“_render”属性










网友评论