Vue数据响应式

93 阅读2分钟

什么是数据响应式

  • 简单来说,响应式就是当修改了vm中的数据时,Vue会通知到使用该数据的代码,自动更新视图。
  • 例如:
const vm = new Vue ({
data:{n:0}
})

在上面的代码中,vm相当于data的代理,当修改vm.ndata.n(数据改变)时,UI中的n就会做出响应,该联动过程即为Vue的数据响应式

Object.defineProperty

Vue2是通过Object.defineProperty()方法来实现数据响应式的。

let vm = new Vue({
  data: {
    obj: {
      a: 0 
    } 
  }
})

以上代码举例,会通过Object.defineProperty()将a用一个含getter/setter的虚拟属性替代,这样就实现对a数据的读写和监听。 再通过在data外层包裹一层代理(一层包含getter/setter虚拟属性的对象),实现实例对象vmdata的代理。即必须通过vm更改data内已声明的数据。

vm.obj.a = 2 //可以更改
this.obj.a =2 //可以更改
this.data.obj.a =2 //不可以更改

新增属性

当我们以普通的方式增添新数据(实例化vue对象时未声明该属性)时,Vue并不会进行对该数据的监听,也就不会进行后续的渲染。

new Vue({
  data: { 
    obj: { 
      a: 0 // obj.a 会被 Vue 监听 & 代理
    }
  }, 
  template: `
    <div> {{obj.b}} <button @click="setB">set b</button>\
    </div> 
`, 
 methods: { 
   setB() { 
     this.obj.b = 1; //页面中不会渲染出b值,因为b未被Vue监听 
   } 
  } 
}).$mount("#app");

上述代码中只有obj.a会被监听,这时候去更改obj.b就没有效果,因为obj.b在一开始就没有写在数据里。

解决办法:

  • 在不事先声明key的情况下,增加属性的方法有Vue.setthis.$set两者等价。
  • 这两个api都可以新增key,同时创建代理和监听,并触发UI更新。

代码示例:

 methods: {
    setB() {
      Vue.set(obj,"b",1)
    }
  }

新增数组

当数据中含有数组时,当我们想为数组添加元素时,新增元素的index在声明实例时未定义,也会面临相同的情况(数组是一种特殊的对象,property为数字的对象)。此时我们也应该采取一些措施,好在vue的作者为我们将数组的七种方法进行了变异,这七种方法分别是

  • pop()
  • push()
  • shift()
  • unshift()
  • splice()
  • splice()
  • sort()
  • reverse()

Vue作者为Array()函数通过继承,新增了一条原型链环节,在该环节中添加了上述七种方法,并方法内部进行了Vue.set()方法的操作,使数组的新元素可以被Vue实例对象监听和代理。