初学vue,你得知道我们是从new Vue
开始的:
new Vue({
el: '#app',
data: obj,
...
})
那你觉得是不是很有意思,咱们new Vue
之后,就可以使用他那么多的功能,可见Vue是暴出来的一个一个功能类函数,我们进入源码一探究竟:
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'
/** * 添加全局的API */
initGlobalAPI(Vue)
/** * 服务端渲染需要 */
Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
})
/** * 服务端渲染需要 */
Object.defineProperty(Vue.prototype, '$ssrContext', {
get () {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
})
/** * 服务端渲染需要 */
Object.defineProperty(Vue, 'FunctionalRenderContext', {
value: FunctionalRenderContext
})
/** * vue版本号 这里的'__VERSION__'为占位符,发布版本时将被自动替换 */
Vue.version = '__VERSION__'
export default Vue
那么我们看到咱们的核心Vue
来自'./instance/index'
那我们再去一探究竟,可想而知里面必定有一个Vue函数类
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'
// Vue构造函数必须使用new关键字实例化, 否则会抛出一个警告, 实例化Vue的时候会调用_init方法初始化
// 这里options也是.vue文件中暴露出的对象
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
可以看到里面有一个function Vue
功能类,而且里面加载了initMixin
,stateMixin
等,这几个方法分别传入了Vue来初始化一些功能。
另外我们可以在入口文件出看到initGlobalAPI
这个方法,那么我们打开initGlobalAPI
所在的位置:./global-api/index
参考Vue3源码视频讲解:进入学习
......
export function initGlobalAPI (Vue: GlobalAPI) {
// config
// 提供获取配置项的方法, 不允许在这里设置配置项
const configDef = {
}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
configDef.set = () => {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
)
}
}
Object.defineProperty(Vue, 'config', configDef)
// exposed util methods.
// NOTE: these are not considered part of the public API - avoid relying on
// them unless you are aware of the risk.
// 注册全局工具API, 只对Vue生效。
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive
}
//定义全局属性
Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick
// 初始化options
Vue.options = Object.create(null)
ASSET_TYPES.forEach(type => {
Vue.options[type + 's'] = Object.create(null)
})
// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.
// 用_base属性来挂载Vue构造器
Vue.options._base = Vue
extend(Vue.options.components, builtInComponents)
//定义全局方法
initUse(Vue) // Vue.use
initMixin(Vue) // Vue.mixin
initExtend(Vue) // Vue.extend
initAssetRegisters(Vue)
}
可见暴露出多个方法给全局,而Vue.util是一些工具方法:
import config from '../config'
import {
initUse } from './use'
import {
initMixin } from './mixin'
import {
initExtend } from './extend'
import {
initAssetRegisters } from './assets'
import {
set, del } from '../observer/index'
import {
ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'
import {
warn,
extend,
nextTick,
mergeOptions,
defineReactive
} from '../util/index'
那么我们回到Vue功能函数类上:
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'
// Vue构造函数必须使用new关键字实例化, 否则会抛出一个警告, 实例化Vue的时候会调用_init方法初始化
// 这里options也是.vue文件中暴露出的对象
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
我们可以看到initMixin(Vue)
执行了,那么我们去读一下init的源码:
import config from '../config'
import {
initProxy } from './proxy'
import {
initState } from './state'
import {
initRender } from './render'
import {
initEvents } from './events'
import {
mark, measure } from '../util/perf'
import {
initLifecycle, callHook }