什么叫数据响应式?
数据响应式是指用户更改数据(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