这一节我们将分析vue里面的各种初始化
options初始化
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
合并后的结果
beforeCreate: [ƒ]
components: {}
computed: {user: ƒ}
created: [ƒ]
data: ƒ mergedInstanceDataFn()
directives: {}
el: "#app"
filters: {}
methods: {handlerUser: ƒ}
mounted: [ƒ]
watch: {a: ƒ}
_base: ƒ Vue(options)
- 通过mergeOptions初始化,mergeOptions讲解参考Vue源码02
生命周期初始化
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')
这里主要讲解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)
}
}
这里对props,methods,data,computed,watch分别进行了处理
initProps
function initProps (vm: Component, propsOptions: Object) {
const propsData = vm.$options.propsData || {}
const props = vm._props = {} // 挂载_props
...
const keys = vm.$options._propKeys = []
if (!isRoot) {
toggleObserving(false)
}
for (const key in propsOptions) {
keys.push(key)
// 对prop的值的计算validateProp详细去看
// 先采用propsData没有则取默认值
const value = validateProp(key, propsOptions, propsData, vm)
....
defineReactive(props, key, value) // 添加响应式
if (!(key in vm)) {
proxy(vm, `_props`, key) // 代理,通过this直接访问
}
}
}
- 全局挂载_props,
- 对props的值,进行全局配置
- 添加响应式
- 添加代理
initData
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm) // 函数执行后在赋值
: data || {}
const keys = Object.keys(data)
while (i--) {
const key = keys[i]
....
proxy(vm, `_data`, key) //代理
}
observe(data, true) // 添加响应式
- 全局挂载_data
- 对data进行处理,判断是否是函数还是对象
- 添加代理
- 添加响应式
initComputed
const watchers = vm._computedWatchers = Object.create(null) // 创建watchers
for (const key in computed) {
const userDef = computed[key]
const getter = typeof userDef === 'function' ? userDef : userDef.get
....
if (!isSSR) {
watchers[key] = new Watcher( // 实例Watcher
vm,
getter || noop,
noop,
computedWatcherOptions // {lazy:true}
)
}
if (!(key in vm)) {
defineComputed(vm, key, userDef) // 代理vm
}
....
}
// defineComputed
export function defineComputed (
target: any,
key: string,
userDef: Object | Function
) {
const shouldCache = !isServerRendering()
sharedPropertyDefinition.get = shouldCache
? createComputedGetter(key)
: createGetterInvoker(userDef)
sharedPropertyDefinition.set = noop
...
Object.defineProperty(target, key, sharedPropertyDefinition) //代理
}
// createComputedGetter
function createComputedGetter (key) {
return function computedGetter () {
const watcher = this._computedWatchers && this._computedWatchers[key] // 通过key拿到watcher
if (watcher) {
if (watcher.dirty) {
watcher.evaluate() // 计算
}
if (Dep.target) {
watcher.depend() // Sub搜集Watcher
}
return watcher.value
}
}
}
- 添加_computedWatchers
- 生成Watcher
- 添加代理 {lazy:true} 不会立即查值
- 在get的时候,通过控制dirty控制
initWatch
function initWatch (vm: Component, watch: Object) {
for (const key in watch) { // {a:handlerChange(old,newV){}}
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)
}
}
}
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) // 这里使用$watch
}
...
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) // 对cb进行递归
}
options = options || {}
options.user = true // 设置user为true
const watcher = new Watcher(vm, expOrFn, cb, options) //实例
if (options.immediate) {
cb.call(vm, watcher.value)
}
return function unwatchFn () {
watcher.teardown() // 移除sub
}
}
- 解析watch的参数
- 设置options.user = true在执行run的时候 会返回oldval
initMethods
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) // 挂载是vm实例上
}
}
- 添加代理
- 绑定作用域