一.解析src/core/index.js
import Vue from './instance/index'
//导入vue实例,包含初始化实例操作,数据响应,实例方法/事件,生命周期,数据渲染
import { initGlobalAPI } from './global-api/index'
//2. 暴露一些全局方法,如set,nextTick,delete等方法
import { isServerRendering } from 'core/util/env'
//检测vue服务器渲染器
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
//为ssr运行时助手安装公开FunctionalRenderContext
Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
})
Object.defineProperty(Vue, 'FunctionalRenderContext', {
value: FunctionalRenderContext
})
Object.defineProperty(Vue.prototype, '$ssrContext', {
get () {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
})
简单总结:初始化vue,暴露属性,方法等,以及isServerRendering等主要用于被调用时获取相关信息
二.解析src/instance/index.js 主要体现
//创建构造函数并且初始化
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: Class) 主要内容
- 函数里面有一个 Vue.prototype._init方法,
vm- 实例自身
const vm: Component = this
// a uid
vm._uid = uid++
内容: 组件this指向,并且对每个组件进行唯一赋值
if (options && options._isComponent) {
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
内容:合并选项,如果有options并且是个组件 优化内部组件实例化 否则走和合并俩个对象
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
内容:暴露自身,并且初始化生命周期,初始化事件,初始化渲染,并且执行beforeCreate,和created,在两者之间渲染state,依赖注入
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
内容:如果发Vue实例使用的根 DOM 元素,则进行挂载
举例说明:
var MyComponent = Vue.extend({
template: '<div>Hello!</div>'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)
单元总结:
-
刚进来先进行init方法,给组件复制uid
-
合并options对象
-
进行初始化渲染:实列数据/方法、事件,渲染函数的执行,执行beforeCreate 和 created期间,在两者之间渲染state,依赖注入
-
最后挂载到Dom节点
stateMixin (Vue: Class)
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) {
const info = `callback for immediate watcher "${watcher.expression}"`
pushTarget()
invokeWithErrorHandling(cb, vm, [watcher.value], vm, info)
popTarget()
}
return function unwatchFn () {
watcher.teardown()
}
}
单元总结:
Vue 实例代理了对其 data、props 对象 property 的访问,添加delete,$watch实例方法
eventsMixin (Vue: Class)
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component
Vue.prototype.$once = function (event: string, fn: Function): Component
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component
Vue.prototype.$emit = function (event: string): Component
单元总结:创建once,emit实例事件方法,这里就不细讲了
lifecycleMixin (Vue: Class
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
const vm: Component = this
const prevEl = vm.$el
const prevVnode = vm._vnode
const restoreActiveInstance = setActiveInstance(vm)
vm._vnode = vnode
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
if (!prevVnode) {
// initial render
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
} else {
// updates
vm.$el = vm.__patch__(prevVnode, vnode)
}
restoreActiveInstance()
// update __vue__ reference
if (prevEl) {
prevEl.__vue__ = null
}
if (vm.$el) {
vm.$el.__vue__ = vm
}
// if parent is an HOC, update its $el as well
if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
vm.$parent.$el = vm.$el
}
// updated hook is called by the scheduler to ensure that children are
// updated in a parent's updated hook.
}
内容:_update首次渲染以及更新时都会被调用,核心是vm.path,全局需要你会看到Vue.prototype.__patch__ = inBrowser ? patch : noop 如果是在浏览器环境就会调用内置模块createPatchFunction
单元总结:创建destroy生命周期,以及更新时触发_update方法
renderMixin (Vue: Class)
installRenderHelpers(Vue.prototype)//安装时的工具
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this)
}
Vue.prototype._render =function (): VNode {
单元总结:渲染时,先调用辅助工具,创建$nextTick,返回虚拟节点
三.解析'src/global-api/index'
initGlobalAPI(Vue)
内容:导入定义好的Vue,已经完成——init方法
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)
内容:Vue.config 定义的全局配置。可以在启动应用之前修改下列 property
如图:
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive
}
内容:暴露一些方法,不是公共API的一部分,基本用不到
Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick
// 2.6 explicit observable API
Vue.observable = <T>(obj: T): T => {
observe(obj)
return obj
}
Vue.options = Object.create(null)
Vue.options = Object.create(null)
ASSET_TYPES.forEach(type => {
Vue.options[type + 's'] = Object.create(null)
})
内容:Vue.observable实现响应对象,ASSET_TYPES实际指向component,directive,filter
如图:
总结:
实现Vue配置,以及相关的配置属性
其他文件`
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
})
Object.defineProperty(Vue.prototype, '$ssrContext', {
get () {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
})
内容:主要用于被调用时获取相关信息