從vue源碼的屬性合併理解方法mergeField 的策略模式

在vue源碼中,我們進行參數屬性合併的時候有一個很關鍵的方法mergeField,這個方法的實現用到了一個很關鍵的設計模式,策略設計模式

  function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }

那麼什麼是策略模式呢,看下面的定義:

意圖:定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。

主要解決:在有多種算法相似的情況下,使用 if...else 所帶來的複雜和難以維護(幫助我們更好的解決多重if-else的判斷)。

何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行爲。

如何解決:將這些算法封裝成一個一個的類,任意地替換。

關鍵代碼:實現同一個接口(在js中實際就是不同的方法依賴同一個對象,如果用ts也可以實現用接口的理念理解)

  1. data的合併策略,即該文件中的strats.data函數
strats.data = function (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    if (childVal && typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.',
        vm
      )

      return parentVal
    }
    return mergeDataOrFn(parentVal, childVal)
  }

  return mergeDataOrFn(parentVal, childVal, vm)
}
  1. watch的合併策略。
    strats.watch = function (
      parentVal: ?Object,
      childVal: ?Object,
      vm?: Component,
      key: string
    ): ?Object {
      // work around Firefox's Object.prototype.watch...
      if (parentVal === nativeWatch) parentVal = undefined
      if (childVal === nativeWatch) childVal = undefined
      /* istanbul ignore if */
      if (!childVal) return Object.create(parentVal || null)
      if (process.env.NODE_ENV !== 'production') {
        assertObjectType(key, childVal, vm)
      }
      if (!parentVal) return childVal
      const ret = {}
      extend(ret, parentVal)
      for (const key in childVal) {
        let parent = ret[key]
        const child = childVal[key]
        if (parent && !Array.isArray(parent)) {
          parent = [parent]
        }
        ret[key] = parent
          ? parent.concat(child)
          : Array.isArray(child) ? child : [child]
      }
      return ret
    }

     

  2.  

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章