Fork me on GitHub

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)
  }
})
posted @   zerozhupan  阅读(534)  评论(2编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示
目 录 X
模仿VUE2实现响应式
Vue2: 通过Object.defin···
Vue3: 通过proxy实现