Vue源码04-initState

这一节我们将分析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实例上
  }
}
  • 添加代理
  • 绑定作用域
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343