讀Vue原始碼 (依賴收集與派發更新)

2022-08-23 20:54:12 字數 3695 閱讀 4785

vue的依賴收集是定義在definereactive方法中,通過object.defineproperty來設定getter,紅字部分主要做依賴收集,先判斷了dep.target如果有的情況會執行紅字邏輯進行依賴收集過程

const getter = property &&property.get

if (!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 default

class dep

addsub (sub: watcher)

removesub (sub: watcher)depend ()

}notify ()

}}

adddep是定義值watcher類下面的乙個方法,通過一些邏輯判斷是否存在,在執行上面dep的addsub方法,將渲染watcher push 到subs陣列裡,然後我們看下是什麼時候將dep.tartget賦值的

adddep (dep: dep) 

}}

在我們呼叫mountcomponent方法時,會例項化watcher

export function

mountcomponent (

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: function

reactivesetter (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 function

queuewatcher (watcher: watcher)

else

queue.splice(i + 1, 0, watcher)

}//queue the flush

if (!waiting)

}}

flushschedulerqueue,首先對佇列wacher進行排序,主要為了處理父子元件,userwatcher等情況,然後呼叫watcher.run方法

function

flushschedulerqueue () "`

: `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...