vue2的数据响应式

752 阅读2分钟

什么叫数据响应式?

数据响应式是指用户更改数据(data)时,视图可以自动刷新,页面UI能够响应数据的变化

如何侦测数据的变化

Object.defineProperty

Object.defineProperty可以给对象添加属性value
可以给对象添加getter/setter
getter/setter用于对属性的读写进行监控

一般可以这么定义一个对象

let data = {
 n:0
}

使用Object.defineProperty定义n

let data = {}  
Object.defineProperty(data,'n',{
  value: 0
})
console.log(data.n) // 0

get如何使用

let obj = {
  姓:“周”,
  名: "杰伦",
  get 姓名(){
   return this.姓 + this.名
  }
}
console.log(obj.姓名) //周杰伦

我们可以理解getter被调用时,是不需要加括号的

set如何使用

let obj = {
  姓:“周”,
  名: "杰伦",
  get 姓名(){
   return this.姓 + this.名
  }
  set 姓名(xxx){
    this.姓 = xxx[0]
    this.名 = xxx.slice(1)
  }
}

obj.姓名 = '方文山'  
console.log(`姓${obj.姓},名${obj3.名}`)

我们可以理解为,用 = xxx会触发set函数

vue对data做了什么

在声明Vue实例对象的时候,会初始化data,在初始化data中的数据后,vue会通过Object.defineProperty()方法来为key添加getter和setter方法,实现data中数据的读写操作。以达到监听的目的,data中的每个数据都会进行遍历,然后使用这个方法来实现添加监听,在添加监听后,防止用户直接修改data中的内容,vue让其实例对象成为data对象的代理,至此,vue实现了对data中数据的监听和代理操作

Object.defineProperty的问题

Object.defineProperty(obj,'n',{...}),必须要一个'n',才能监听obj.n

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;
  }
 }
}).$mount("#app");

理论上,点击setB按钮,视图上会显示1,但是并没有,因为vue没办法监听不存在的obj.b

解决办法
1、把key都声明好,后面再添加属性
2、使用Vue.set或者this.$set

new Vue({
 data: {
 obj: {
   a: 0 // obj.a 会被 Vue 监听 & 代理
   }
 },

template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
  this.$set(this.obj,"b",1)
  //或 Vue.set(this.obj,"b",1)
  }
 }
}).$mount("#app");

此时,点击setB,视图上会显示1。

Vue.set和this.$set的作用

1、新增key
2、自动创建代理和监听(如果没有创建过)
3、触发UI更新(不会立刻更新)

data中有数组怎么办

new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,

methods: {
  setD() {
    this.array[3] = "d"; //请问,页面中会显示 'd' 吗?
   }
  }
}).$mount("#app");

此刻,点击setD并不会显示d

解决办法
1、每次修改数组使用Vue.set或this.$set

//源代码不变,只修改methods里的代码  
 methods: {
   setD() {
   this.$set(this.array,3,d)
   //或者 this.array.push("d")
  }
 }

2、 使用vue给我们提供的变异方法
vue为我们提供的数组数组变异方法有:push(),pop(),shift(),unshift(),splice(),sort(),reverse(),它们通过原型链/继承的方式,实现了vue对其数据的监听和代理。

总结

对象中新增的key

  • vue没有办法事先监听和代理
  • 要使用set来新增key,创建监听和代理,更新UI
  • 最好提前把属性都写出来,不要新增key
  • 但数组做不到(不新增key)

数组中新增的key

  • 也可以使用set来新增key,更新UI
  • vue提供了7个API方便对数组进行增删
  • 这7个API会自动处理监听和代理,并且更新UI

参考链接

blog.csdn.net/XH_jing/art…
www.zhihu.com/search?type…