對比Object.defineProperty()和proxy對數組監聽的處理

對比Object.defineProperty()和proxy對數組監聽的處理

Object.defineProperty()方法用於給對象添加屬性,無法直接給數組添加或刪除元素,可以通過爲對象添加一個數組類型的屬性,如下:

let obj = {}
Object.defineProperty(obj, 'a', {
  configurable: true,
  enumerable: true,
  get: () => {
    console.log('get value by defineProperty')
    return val
  },
  set: (newVal) => {
    console.log('set value by defineProperty')
    val = newVal
  }
})

obj.a = [] // set value by defineProperty
obj.a.push('1') // get value by defineProperty
obj.a[0] = 1 // get value by defineProperty
obj.a.pop(1) // get value by defineProperty
obj.a = [1, 2, 3] // set value by defineProperty

從上面例子中可以看出,使用Object.defineProperty()爲對象添加數組類型屬性後,當使用數組自身的一些方法如push、pop等爲數組添加或刪除元素時,不能觸發屬性a的setter,無法實現對屬性a中元素的實時監聽,這也就是Vue中重寫數組方法的原因。

值得注意的是上面使用push、pop、直接通過索引爲數組添加元素時會觸發屬性a的getter,是因爲與這些操作的返回值有關,以push方法爲例,使用push方法爲數組添加元素時,push方法返回值是添加之後數組的新長度,當訪問數組新長度時就會自然而然觸發屬性a的getter。

proxy可以直接代理數組,我們可以直接對數組進行處理,如下:

let arr = []
let arrProxy = new Proxy(arr, {
  get: (target, prop) => {
    console.log('get value by proxy')
    return prop in target ? target[prop] : undefined
  },
  set: (target, prop, value) => {
    console.log('set value by proxy')
    target[prop] = value
    return true
  }
})

arrProxy.push(1)
// get value by proxy  // 獲取數組arr的push方法
// get value by proxy  // 獲取數組arr的length屬性
// set value by proxy  // 設置arr[0] = 1
// set value by proxy  // 設置數組arr長度爲1

arrProxy[0] = 1
// set value by proxy

arrProxy[0] = 2
// set value by proxy

從上面例子中可以看出當使用proxy代理數組時,調用數組的push方法可以觸發一系列操作,具體如下:觸發數組的getter,獲取數組arr的push方法;觸發數組的getter,獲取arr的length屬性;觸發數組的setter,設置arr[0] = 1;觸發數組的setter,設置數組arr的長度爲1;直接使用索引值進行添加改變元素時也會觸發數組arr的setter。

通過對比Object.defineProperty()和proxy對數組監聽的處理,可以發現proxy不但可以直接監聽數組,而且代理數組後可以監聽到數組常用的方法對數組產生的改變,比Object.defineProperty()更方便更強大,這也是Vue 3.0使用proxy進行數據監聽的原因。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章