这是我参与更文挑战的第6天,活动详情查看: 更文挑战
beforeCreated
初始化界面前
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options?: Object) {
const vm: Component = this
...设置Vue元素的uid唯一值,设置Vue对象的_isVue避免被观察
... 参数合并
... 初始化this._renderProxy属性,_self指向自己this
initLifecycle(vm) // 初始化一些参数
initEvents(vm) // 初始化事件
initRender(vm) // 初始化渲染函数
callHook(vm, 'beforeCreate')
}
}
复制代码
initLifecycle
的实现
export function initLifecycle (vm: Component) {
const options = vm.$options
let parent = options.parent
// 找到父节点然后将当前元素和父节点进行关联
if (parent && !options.abstract) {
while (parent.$options.abstract && parent.$parent) {
parent = parent.$parent
}
parent.$children.push(vm)
}
vm.$parent = parent
vm.$root = parent ? parent.$root : vm
vm.$children = []
vm.$refs = {}
vm._watcher = null
vm._inactive = null
vm._directInactive = false
vm._isMounted = false
vm._isDestroyed = false
vm._isBeingDestroyed = false
}
复制代码
initLifecycle
主要是初始化一些参数,其中主要是对当前vue
对象的parent
元素进行了绑定,已经设置了$root
的属性
initEvents
的实现
export function initEvents (vm: Component) {
vm._events = Object.create(null)
vm._hasHookEvent = false
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners) // 更新组件的时间监听
}
}
复制代码
-
export function updateComponentListeners ( vm: Component, listeners: Object, oldListeners: ?Object ) { target = vm updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm) // 更新监听器 target = undefined } 复制代码
-
作用:更新组件的事件监听
initRender
的实现
export function initRender (vm: Component) {
vm._vnode = null
vm._staticTrees = null
const options = vm.$options
const parentVnode = vm.$vnode = options._parentVnode
const renderContext = parentVnode && parentVnode.context
vm.$slots = resolveSlots(options._renderChildren, renderContext)
vm.$scopedSlots = emptyObject
// 设置_c属性和$createElement属性的对应的方法
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
const parentData = parentVnode && parentVnode.data
// 给vm对象添加个响应式的对象,并进行验证提示
if (process.env.NODE_ENV !== 'production') {
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
!isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
}, true)
defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => {
!isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
}, true)
} else {
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, null, true)
defineReactive(vm, '$listeners', options._parentListeners || emptyObject, null, true)
}
}
复制代码
综上所述:在beforeCreated
之前做的主要对一些参数的初始化,所以此时的时候 options中的data和this还未进行绑定
created
数据已经绑定到this上
initInjections(vm)
initState(vm)
initProvide(vm)
callHook(vm, 'created')
复制代码
-
initInjections
的实现-
export function initInjections (vm: Component) { const result = resolveInject(vm.$options.inject, vm) // 分解inject对象 if (result) { toggleObserving(false) Object.keys(result).forEach(key => { if (process.env.NODE_ENV !== 'production') { defineReactive(vm, key, result[key], () => { warn( `Avoid mutating an injected value directly since the changes will be ` + `overwritten whenever the provided component re-renders. ` + `injection being mutated: "${key}"`, vm ) }) } else { defineReactive(vm, key, result[key]) } }) toggleObserving(true) } } 复制代码
- 循环将分解得到的
inject
绑定到this
实例对象上
- 循环将分解得到的
-
export function resolveInject (inject: any, vm: Component): ?Object { if (inject) { const result = Object.create(null) const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject) for (let i = 0; i < keys.length; i++) { const key = keys[i] if (key === '__ob__') continue const provideKey = inject[key].from // 这个私钥是干啥用的呢? let source = vm // 这里不明白, 这个_provided是干什么的 while (source) { if (source._provided && hasOwn(source._provided, provideKey)) { result[key] = source._provided[provideKey] break } source = source.$parent } if (!source) { if ('default' in inject[key]) { const provideDefault = inject[key].default result[key] = typeof provideDefault === 'function' ? provideDefault.call(vm) : provideDefault } else if (process.env.NODE_ENV !== 'production') { warn(`Injection "${key}" not found`, vm) } } } return result } } 复制代码
- 这个函数主要是分解
inject
对象,具体中间的内容需要之后进行整理
- 这个函数主要是分解
-
-
initState
的实现-
export function initState (vm: Component) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm, opts.props) if (opts.methods) initMethods(vm, opts.methods) if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */) } if (opts.computed) initComputed(vm, opts.computed) if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) } } 复制代码
$options
参数中的props
|methods
|data
|computed
|initWatch
属性进行初始化,应该是将这些对象中的数据直接和this
实例对象进行绑定
-
function initProps (vm: Component, propsOptions: Object) { .... for (const key in propsOptions) { const value = validateProp(key, propsOptions, propsData, vm) // 获取指定格式的值 if (process.env.NODE_ENV !== 'production') { ...格式化key,并进行验证 // 将props中的key都设置成可以被监听的 defineReactive(props, key, value, () => { if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop directly since the value will be ` + `overwritten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${key}"`, vm ) } }) } else { defineReactive(props, key, value) } if (!(key in vm)) { proxy(vm, `_props`, key) } } toggleObserving(true) } 复制代码
-
function initMethods (vm: Component, methods: Object) { const props = vm.$options.props for (const key in methods) { .... 验证 vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm) // 将方法绑定到this实例对象上 } } 复制代码
-
function initData (vm: Component) { let data = vm.$options.data const keys = Object.keys(data) ... 对于data中的数据进行校验判断是否已经在其他的methods/props中已被注册过了,如 果过了就提示,没有注册就进行注册,将代理到this._data[key]上 observe(data, true /* asRootData */) // 对data中的数据进行观察 } 复制代码
-
function initComputed (vm: Component, computed: Object) { const watchers = vm._computedWatchers = Object.create(null) const isSSR = isServerRendering() //TODO:判断是否是服务渲染的 for (const key in computed) { const userDef = computed[key] const getter = typeof userDef === 'function' ? userDef : userDef.get ...检查 } if (!isSSR) { // 创建监听器,给computed做监听 watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions //{ lazy: true } ) } if (!(key in vm)) { // 直接将computed中的属性绑定到了this对象上了 defineComputed(vm, key, userDef) // 在vue实例对象上添加一个computed的key的属性进行set和get的监听事件 } ...与其他属性进行验证判断是否名称重复了呢 } } 复制代码
- 先循环获取
computed
中的自定义执行函数,然后对每个属性设置监听 - 然后将每个
computed
属性绑定到this
实例对象上
- 先循环获取
-
function initWatch (vm: Component, watch: Object) { for (const key in watch) { const handler = watch[key] if (Array.isArray(handler)) { for (let i = 0; i < handler.length; i++) { createWatcher(vm, key, handler[i]) // 生成监听器 } } else { createWatcher(vm, key, handler)// 调用了$watch方法来将函数实现对元素的监听 } } } function createWatcher ( vm: Component, expOrFn: string | Function, handler: any, options?: Object ) { if (isPlainObject(handler)) { options = handler handler = handler.handler } if (typeof handler === 'string') { handler = vm[handler] } return vm.$watch(expOrFn, handler, options) } 复制代码
-
综上所述:对于options
中的属性都将属性直接绑定到了this
实例对象上,并对属性都设置了响应式处理
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END