vue源码解析之选项合并(二)
選項 data 的合并策略
我們跳過mergeData?以及?mergeDataOrFn,我們暫且不關注這兩個函數的作用。暫且跳過繼續看下面的代碼:
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) }在strats策略對象上面添加了一個data策略函數,進行選項data的策略合并
if (!vm) {}如同上一篇文章介紹一樣 用來判斷是否是子組件選項,如果是子組件選項 return mergeDataOrFn(parentVal, childVal)
如果不是 return mergeDataOrFn(parentVal, childVal, vm)
再來看看if判斷里面的內容: if (childVal && typeof childVal !== 'function') {}
判斷是否又子組件的data,并且檢測是否是一個function,如果不是函數則會警告,并且返回parentVal
? ? ? ? 如果childval是函數 則會返回mergeDataOrFn(parentVal, childVal) 執行結果
? ? ? ?后面就不用說了, 如果又vm 就執行mergeDataOrFn(parentVal, childVal, vm)
接下來我們看看一直調用的mergeDataOrFn函數是什么:
/*** Data*/ export function mergeDataOrFn (parentVal: any,childVal: any,vm?: Component ): ?Function {if (!vm) {// in a Vue.extend merge, both should be functionsif (!childVal) {return parentVal}if (!parentVal) {return childVal}// when parentVal & childVal are both present,// we need to return a function that returns the// merged result of both functions... no need to// check if parentVal is a function here because// it has to be a function to pass previous merges.return function mergedDataFn () {return mergeData(typeof childVal === 'function' ? childVal.call(this, this) : childVal,typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal)}} else {return function mergedInstanceDataFn () {// instance mergeconst instanceData = typeof childVal === 'function'? childVal.call(vm, vm): childValconst defaultData = typeof parentVal === 'function'? parentVal.call(vm, vm): parentValif (instanceData) {return mergeData(instanceData, defaultData)} else {return defaultData}}} }整體的也是和之前的幾個函數一樣 首先對vm的判斷,其中就mergeData函數需要介紹下,看下mergeData源碼,這個函數是用來干嘛的
/*** Helper that recursively merges two data objects together.*/ function mergeData (to: Object, from: ?Object): Object {// 沒有 from 直接返回 toif (!from) return tolet key, toVal, fromValconst keys = Object.keys(from)// 遍歷 from 的 keyfor (let i = 0; i < keys.length; i++) {key = keys[i]toVal = to[key]fromVal = from[key]// 如果 from 對象中的 key 不在 to 對象中,則使用 set 函數為 to 對象設置 key 及相應的值if (!hasOwn(to, key)) {set(to, key, fromVal)// 如果 from 對象中的 key 也在 to 對象中,且這兩個屬性的值都是純對象則遞歸進行深度合并} else if (isPlainObject(toVal) && isPlainObject(fromVal)) {mergeData(toVal, fromVal)}// 其他情況什么都不做}return to }接收兩個參數,to,from;
? ?根據調用傳參??to?對應的是?childVal?產生的純對象,from?對應?parentVal?產生的純對象
??這個函數作用就是:將?from?對象的屬性混合到?to?對象中,也可以說是將?parentVal?對象的屬性混合到?childVal?中,最后返回的是處理后的?childVal?對象。
?合并階段?strats.data?將被處理成一個函數,但是這個函數并沒有被執行,而是到了后面初始化的階段才執行的,
重點:!!!!!!!!!!!
mergeData?函數只有在初始化的時候才會執行,進行數據合并;
?Vue?的初始化的時候,?inject?和?props?這兩個選項的初始化是先于?data?選項的,這就保證了我們能夠使用?props?初始化?data?中的數據
?
轉載于:https://www.cnblogs.com/xweizi/p/10551938.html
總結
以上是生活随笔為你收集整理的vue源码解析之选项合并(二)的全部內容,希望文章能夠幫你解決所遇到的問題。