Vue 3 深刻響應性原理

深刻響應性原理

終於到了講解咱們 Vue 的響應式原理,前面咱們已經講解了 MapWeakMapSetWeakSetProxyReflect 這幾個知識點。那麼接下來思考下到底什麼是響應式,就好比咱們作一個公司的官網,而後要求必須兼容手機端,ipad 端,電腦端,內容屏幕大小變化而變化,這些就須要依賴 JavaScript,CSS, HTML 去處理了。ide

那麼假如咱們像在 Excel 表格中,兩個數字相加,若是一個數字變化了,兩個數字的和確定得變化吧,Excel 表格作到了,可定裏面是作了很大的處理了,那若是使用 JavaScript 來作,咱們該如何作呢?函數

let var1 = 2
let var2 = 3

let sum = var1 + var2

// 當 var1 變化時,

// 該如何通知 sum

若是咱們更新第一個值,sum 不會被修改。this

那麼咱們如何用 JavaScript 實現這一點呢?url

  • 檢測其中某一個值是否發生變化
  • 用跟蹤 (track) 函數修改值
  • 用觸發 (trigger) 函數更新爲最新的值

Vue 如何追蹤變化?

在 Vue 中,在將一個對象數據傳遞給一個組件的時候,Vue 已經給我這些數據設置了 settergetter 屬性,一旦數據發生變化,就會獲得響應,這其中就是 ProxyReflect 的很大的功勞。spa

經過前面的知識,咱們知道 Proxy 是一個包含另外一個對象或函數並容許你對其進行攔截的對象。3d

let obj = {
    var12,
    var23,
    sum0,
}
let handlerObj = {
    get(target, prop) {
        if(prop == 'sum') {
            target['sum'] = target['var1'] + target['var2']
            return target['sum']
        }
        return target[prop]
    },
    set(target, prop, newVal) {
        target[prop] = newVal
    }
}
let p = new Proxy(obj, handlerObj)
console.log(p.sum)

圖片

此外,Proxy 還提供了另外一個特性。咱們沒必要像這樣返回值:target[prop],而是能夠進一步使用一個名爲 Reflect 的方法,它容許咱們正確地執行 this 綁定,就像這樣:
code

let obj = {
    var12,
    var23,
    sum0,
}
let handlerObj = {
    get(target, prop) {
        if(prop == 'sum') {
            target['sum'] = target['var1'] + target['var2']
        }
        return Reflect.get(...arguments)
    },
    set(target, prop, newVal) {
        target[prop] = newVal
    }
}
let p = new Proxy(obj, handlerObj)
console.log(p.sum)

圖片

上面咱們已經檢測到了哪些數據發生了變化,因此接下來咱們須要用一個咱們還沒實現的 track 追蹤方法來進行修改:
orm

let obj = {
    var12,
    var23,
    sum0,
}
let track = (target, prop) => {
    if(prop == 'sum') {
        target['sum'] = target['var1'] + target['var2']
    }
}
let handlerObj = {
    get(target, prop) {
        track(target, prop)
        return target[prop]
    },
    set(target, prop, newVal) {
        target[prop] = newVal
    }
}
let p = new Proxy(obj, handlerObj)
console.log(p.sum)

圖片

最後,當某些內容發生改變時咱們會設置新的值。爲此,咱們將經過觸發這些更改來設置新 Proxy 的更改:
對象

let obj = {
    var12,
    var23,
    sum0,
}
let track = (target, prop) => {
    if(prop == 'sum') {
        target['sum'] = target['var1'] + target['var2']
    }
}
let trigger = (target, prop, newVal) => {
    target[prop] = newVal
}
let handlerObj = {
    get(target, prop) {
        track(target, prop)
        return target[prop]
    },
    set(target, prop, newVal) {
  trigger(target, prop, newVal)
        
        return Reflect.set(...arguments)
    }
}
let p = new Proxy(obj, handlerObj)
console.log(p.sum)

圖片

  • 當某個值發生變化時進行檢測:咱們再也不須要這樣作,由於 Proxy 容許咱們攔截它
  • 跟蹤更改它的函數:咱們在 Proxy 中的 getter 中執行此操做,稱爲 effect
  • 觸發函數以便它能夠更新最終值:咱們在 Proxy 中的 setter 中進行該操做,名爲 trigger
相關文章
相關標籤/搜索