vue的依賴收集是定義在definereactive方法中,通過object.defineproperty來設定getter,紅字部分主要做依賴收集,先判斷了dep.target如果有的情況會執行紅字邏輯進行依賴收集過程
const getter = property &&property.getif (!getter && arguments.length === 2)
const setter = property &&property.set
let childob = !shallow &&observe(val)
object.defineproperty(obj, key, }}
return
value
},
dep是乙個類,target是dep的乙個靜態屬性,是乙個watcher,上面如果有target的話,會執行dep.depend方法,就是呼叫adddep方法
export defaultclass dep
addsub (sub: watcher)
removesub (sub: watcher)depend ()
}notify ()
}}
adddep是定義值watcher類下面的乙個方法,通過一些邏輯判斷是否存在,在執行上面dep的addsub方法,將渲染watcher push 到subs陣列裡,然後我們看下是什麼時候將dep.tartget賦值的
adddep (dep: dep)}}
在我們呼叫mountcomponent方法時,會例項化watcher
export functionmountcomponent (
vm: component,
el: ?element,
hydrating?: boolean
): component
else
}} callhook(vm, 'beforemount')
let updatecomponent
/*istanbul ignore if
*/if (process.env.node_env !== 'production' && config.performance &&mark) `
const endtag = `vue-perf-end:$`
mark(starttag)
const vnode =vm._render()
mark(endtag)
measure(`vue $ render`, starttag, endtag)
mark(starttag)
vm._update(vnode, hydrating)
mark(endtag)
measure(`vue $ patch`, starttag, endtag)}}
else
} //we set this to vm._watcher inside the watcher's constructor
//since the watcher's initial patch may call $forceupdate (e.g. inside child
//component's mounted hook), which relies on vm._watcher being already definednew watcher(vm, updatecomponent, noop, null, true /* isrenderwatcher */)hydrating = false
//manually mounted instance, call mounted on self
//mounted is called for render-created child components in its inserted hook
if (vm.$vnode == null
)
return
vm}
在new watcher的過程中有乙個get方法,會執行pushtargert方法
get ()catch
(e) "`)
} else
} finally
poptarget()
this
.cleanupdeps()
}return
value
}
而pushtarget方法就是將當前的watcher 賦值給dep.target
export function pushtarget (_target: ?watcher)
vue的派發更新,首先獲取原有值和新值,然後對新值和舊值作對比,如果相同什麼也不做,否則將新值賦值給val,如果新值仍然是個物件,則在重新呼叫observe方法將其變成響應式,最後呼叫dep.notify方法
set: functionreactivesetter (newval)
/*eslint-enable no-self-compare
*/if (process.env.node_env !== 'production' &&customsetter)
if(setter)
else
childob = !shallow &&observe(newval)
dep.notify()
}
dep.notyify方法,就是遍歷所有的訂閱者,也就是渲染watcher,使每乙個watcher呼叫update方法
notify ()}
實際就是每個watcher執行queuewatcher()方法
update ()else
if (this
.sync)
else
}
queuewatcher方法,先將watcher push到佇列中,然後再下乙個tick內執行flushschedulerqueue,nexttick就是對promise的一層封裝
export functionqueuewatcher (watcher: watcher)
else
queue.splice(i + 1, 0, watcher)
}//queue the flush
if (!waiting)
}}
flushschedulerqueue,首先對佇列wacher進行排序,主要為了處理父子元件,userwatcher等情況,然後呼叫watcher.run方法
functionflushschedulerqueue () "`
: `in a component render function
.` ),
watcher.vm
)break
} }
}
wathcer.run方法會將新值賦給value
run ()catch
(e) "`)}}
else}}
}
vue原始碼 getter setter 依賴跟蹤
依賴跟蹤 類有兩個方法 depend和notify depend表示當前正在執行的 收集這種依賴項 notify表示依賴發生改變,任何之前被定義過的表示式,計算,函式都會被通知重新執行,所以我們就需要乙個函式或者一段表示式或者某種演算法讓他們產生關聯,並且可以把這種關係叫做依賴,也可以被認為是訂閱者...
vue原始碼系列06 實現陣列的依賴收集
在初始化資料的時候,建立乙個陣列專用的dep 給每個物件新增乙個ob屬性,主要是用於儲存當前例項物件 this 在 array.js 中在資料改變時,觸發陣列專用dep的notify 派發更新 修改 definereactive 方法 export function definereactive d...
讀vue原始碼筆記 1
shared util.js 1.hasown var hasownproperty object.prototype.hasownproperty function hasown obj,key extend export function extend to object,from object...