Vue2和Vue3實現響應式原理對比


模仿VUE2實現響應式

Vue2: 通過Object.defineProperty()來實現

1. 代碼

// 模仿vue2實現響應式
    let person = {
      name: '張三',
      age: 20
    }
    let person_vue2 = {}
    Object.defineProperty(person_vue2, 'name', {
      configurable: true,
      get() {
        console.log('讀取name屬性');
        return person.name
      },
      set(value) {
        console.log('修改name屬性');
        person.name = value
      }
    })
    Object.defineProperty(person_vue2, 'age', {
      get() {
        console.log('讀取age屬性');
        return person.age
      },
      set(value) {
        console.log('修改age屬性');
        person.age = value
      }
    })

2. 一些操作

  • 讀、改 操作可以響應式
    image
  • 給person_vue2添加hobby屬性,可以添加成功,但是set監聽不到,沒有響應式。對應hobby屬性沒有get和set方法。
    image

3.弊端

  • 新增屬性、刪除屬性,界面不會更新
  • 直接通過下標修改數組,界面不會自動更新
  • 要一個屬性一個屬性改(就算使用循環也還是很麻煩)

4. 解決

  • 對象
    this.$set(object,'propName',value)
    Vue.set(object,'propName',value)
    this.$delete(object, 'propName')
    Vue.delete(object, 'propName')
  • 數組
    this.$set(array,index,value)
    this.array.splice()

Vue3: 通過proxy實現

1.初步實現

let person = {
	name: '張三',
	age: 20
	}
	// 模仿vue3實現響應式
	let person_vue3 = new Proxy(person, {})

這時候查看一下增刪改查操作:

  • 查看person_vue3,是一個proxy對象
    image
  • 給person_vue3添加hobby屬性,對應person也有了
    image
  • 修改和刪除屬性類似
    image

2.捕獲操作,實現響應式

let person = {
    name: '張三',
    age: 20
  }
  // 模仿vue3實現響應式
let person_vue3 = new Proxy(person, {
  get(target, propName) {
    console.log(`讀取person_vue3的${propName}屬性`);
    // propName是變量,不可以使用target.propName來讀取屬性
    return target[propName]
  },
  set(target, propName, value) {
    console.log(`修改person_vue3的${propName}屬性`);
    target[propName] = value
  },
  deleteProperty(target, propName) {
    console.log(`刪除person_vue3的${propName}屬性`);
    return target[propName]
})

image

3. Reflect

image

使用ReflectReflect的MDN鏈接

let person = {
    name: '張三',
    age: 20
  }
  // 模仿vue3實現響應式
let person_vue3 = new Proxy(person, {
  get(target, propName) {
    console.log(`讀取person_vue3的${propName}屬性`);
    // propName是變量,不可以使用target.propName來讀取屬性
    // return target[propName]
    return Reflect.get(target, propName)
  },
  set(target, propName, value) {
    console.log(`修改person_vue3的${propName}屬性`);
    // target[propName] = value
    Reflect.set(target, propName, value)
  },
  deleteProperty(target, propName) {
    console.log(`刪除person_vue3的${propName}屬性`);
    // return target[propName]
    return Reflect.deleteProperty(target, propName)
  }
})


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM