Vue2.x之疑點

這是我本身在深刻了解 Vue 過程本身思考過的一些問題,特地拿出來記錄一下,以避免從此遺忘:vue

1.Vue 把數據轉換成響應式數據後,是怎麼來觸發getter從而收集依賴的

解答:Vue 在初始化的過程當中,把數據都轉換成響應式數據。在觸發生命週期函數beforeMount以後經過new Watcher() 來觀測渲染函數。源碼git

2.數組和對象的依賴分別保存在哪

解答:Vue 中數組和對象收集依賴都是在getter 中收集。可是觸發setter 的地方不同。github

由於Vue 監聽數組的變化是經過Array的原型方法來監聽的,因此必需要保證能在原型方法和getter中都可以獲取到 dep ,因此把 dep 保存在 Observer 實例上。(具體的解釋請看響應式原理)express

3.Watcher 監聽函數怎麼監測函數中全部用到的數據的

解答:當用 Watcher 監聽一個函數時,函數裏面每個數據的getter都會觸發,而且此時的 Dep.target 是當前的 Watcher 實例,因此每個數據都會把當前的Watcher 實例收集起來。數組

4.Watcher監聽一個路徑字符串:'a.b.c',會分別監聽a、a.b、a.b.c嗎

解答:會。由於a、a.b、a.b.c的getter都會觸發。函數

5.當數據變化後,多餘的依賴是怎麼處理的

解答:當數據變更後確定會從新觸發getter。源碼this

// Watcher.js 
get () {
    pushTarget(this)
    let value
    const vm = this.vm
    try {
        // 這裏觸發getter
        value = this.getter.call(vm, vm)
    } catch (e) {

        if (this.user) {
            handleError(e, vm, `getter for watcher "${this.expression}"`)
        } else {
            throw e
        }
    } finally {
        // "touch" every property so they are all tracked as
        // dependencies for deep watching
        if (this.deep) {
            traverse(value)
        }
        popTarget()
        // 這裏清理多餘的依賴
        this.cleanupDeps()
    }
    return value
}

cleanupDeps () {
    let i = this.deps.length
    while (i--) {
        const dep = this.deps[i]
        if (!this.newDepIds.has(dep.id)) {
            dep.removeSub(this)
        }
    }
    let tmp = this.depIds
    this.depIds = this.newDepIds
    this.newDepIds = tmp
    this.newDepIds.clear()
    tmp = this.deps
    this.deps = this.newDeps
    this.newDeps = tmp
    this.newDeps.length = 0
}
複製代碼
相關文章
相關標籤/搜索