面试题:Vue2和Vue3双向绑定分别是怎么实现的?

571 阅读2分钟

我们都知道 vue3之前实现双向数据用的是Object.defineProperty()方法,到了vue3则更换为了es5的Proxy方法

proxy相比vue3之前的Object.defineProperty()又有什么好处呢?

我们先搞清楚Object.defineProperty()和proxy分别是怎么实现的双向绑定

vue3之前的:


    const data = {
        name: '',
      }
      // 拷贝一下data对象 防止死循环
      let newData = { ...data }
      Object.defineProperty(data, 'name', {
        get: () => {
          console.log('读取')
          return newData.name
        },
        set: (newval) => {
          console.log('设置')
          newData.name = newval
          response()
        },
      })
      setTimeout(() => {
        data.name = 'hello world'
      }, 1000)
      //输入时为data重新赋值 通知监听的方法为newData更改数据来达到页面新数据的动态呈现
      iptName.oninput = function () {
        data.name = this.value
      }
      const response = () => {
        hName.innerText = data.name
        iptName.value = data.name
      }

image.png 这样我们使用Object.defineProperty() 就实现了一个简单的双向绑定

使用proxy和Object.defineProperty()大同小异,只不过proxy可以直接监听整个data对象,而非data上的某个属性

let data = {
        name: '123',
      }
      data = new Proxy(data, {
        //obj为传入的对象,prop操作的属性
        get(obj, prop) {
          console.log('get', obj, prop)
          return obj[prop]
        },
        //value 更改的新值
        set(obj, prop, value) {
          console.log('set', obj, prop, value)
          obj[prop] = value
          response()
        },
      })
      setTimeout(() => {
        data.name = 'hello world'
      }, 1000)
      iptName.oninput = function () {
        data.name = this.value
      }
      const response = () => {
        hName.innerText = data.name
        iptName.value = data.name
      }

image.png

由此可以看出 proxy比Object.defineProperty还是要方便很多的

Proxy的优势:

1.Proxy可以直接监听整个对象而非属性。

2.Proxy可以直接监听数组的变化。

3.Proxy有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的。

4.Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;

5.Proxy做为新标准将受到浏览器产商重点持续的性能优化,也就是传说中的新标准的性能红利。

Object.defineProperty()的优势呢?

恐怕只有兼容优势了

再说一下Object.defineProperty()的缺点

1.Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。

2.Object.defineProperty不能监听数组。是通过重写数据的那7个可以改变数据的方法来对数组进行监听的。

3.Object.defineProperty 也不能对 es6 新产生的 Map,Set 这些数据结构做出监听。

4.Object.defineProperty也不能监听新增和删除操作,通过 Vue.set()和 Vue.delete来实现响应式的。