前端学习笔记(8)-Vue2和Vue3双向数据绑定原理对比

        在 vue 的 2.x 版本中⽤ object.defineProperty 来实现双向数据绑定原理,⽽在 vue3.0 版本中⽤Proxy 这个对象来代替 object.defineProperty 实现数据的双向绑定。这俩种数据双向绑定都是基于数据劫持来实现的。

1.defineProperty

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法

  • Object.defineProperty(obj, prop, descriptor)

参数

  • obj : 要定义属性的对象。
  • prop:要定义或修改的属性的名称或 Symbol 。
  • descriptor:要定义或修改的属性描述符对象。

返回值

  • 被传递给函数的对象。
  <script>
		let obj = {x:100}
		let obj2 = {y:200}

		
		// 不可枚举 无法更改
		Object.defineProperty(obj2,'x',{
			// value:18,
			
			get(){
				console.log('有人读取')
				// person.age
				return obj.x
			},

			set(value){
				console.log('有人修改value,值为',value)
				obj.x =value
				return number
			}
			// 通过obj2操作obj的x 相当于data数据代理vm
		})

		// 控制台
		console.log(Object.keys(obj))
		console.log(obj)

  </script>

利用 object.defineProperty进行数据劫持也有缺点

1.数组的以下几个方法不会触发 其中的set:

{
    push
    pop
    shift
    unshift
    splice
    sort
    reverse
}

        Vue 把这些方法定义为变异方法 (mutation method),指的是会修改原来数组的方法。与之对应则是非变异方法 (non-mutating method),例如 filter, concat, slice 等,它们都不会修改原始数组,而会返回一个新的数组。

2.必须先将对象的key值遍历后在逐个添加,增加了一层嵌套

Object.keys(obj).forEach(key => {
  Object.defineProperty(obj, key, {
    // ...
  })
})


2.Proxy

核心:

  • 通过Proxy代理:拦截对data任意属性的任意(13种)操作,包括对属性值的读写,属性的添加,属性的删除等
  • 通过Reflect反射:动态对被代理对象的相应数值进行特定的操作。

Proxy对象参数

  • handler:包括捕捉器的占位符对象,可译为处理器对象。用来监视数据的变化,里面有监视的方法
  • target:目标对象
  • traps:类似于捕获器

Reflect对象

  • 反射对象,反射操作,简单来说,将代理对象相关的属性和属性值的返回。

!只能调用其静态方法无法构造 配合handler使用

响应式实现代码例子:

setup() {
    const uesr = {
      name: 'jzy',
      age: 20,
      school: {
        name: 'Jimei',
      },
    const proxyUser = new Proxy(uesr, {
      // handler.get()用于拦截对象的读取属性操作
      get(target, prop) {
        console.log('get方法调用了')
        return Reflect.get(target, prop)
        // 通过反射对象将数据反射出去
      },
      // 修改目标对象属性值/为目标对象添加新的属性
      set(target, prop, val) {
        console.log('set方法调用了')
        return Reflect.set(target, prop, val)
      },
    })
    console.log(proxyUser.name)
    // 通过代理对象更新目标对象上的某个属性值
    proxyUser.name = 'JiangZhengyang'
    // proxyUser.gender = '男'

    console.log(proxyUser.name)
    // delete proxyUser.age
    console.log(proxyUser)
  },

输出: 

3.proxy相较于object.defineProperty的优势

  • 直接监听对象⽽⾮属性
  • 直接监听数组的变化
  • 拦截⽅式较多(有 13 种⽅式)

        apply 、construct、defineProperty、deleteProperty、

        get、getOwnPropertyDescriptor、getPrototypeOf、has、isExtensible

        ownKeys、preventExtensions、set、setPrototypeOf

  • Proxy 返回⼀个新对象,可以只操作新对象达到⽬的,⽽ Object.defineProperty 只能遍历对象属性

Proxy 可以被认为是 Object.defineProperty() 的升级版。外界对某个对象的访问,都必须经过这层拦截。因此它是针对整个对象,而不是对象的某个属性,所以也就不需要对keys 进行遍历。

猜你喜欢

转载自blog.csdn.net/JiangZhengyang7/article/details/127995275