在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也可以實現用接口的理念理解)
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)
}
- 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 }