目录:
1.什么是响应式?
2.Object.defineProperty存在的问题以及解决方案
3.data中有数组怎么办
4.Vue下的数组的变更方法
1.什么是响应式?
我打你一拳,你喊疼,你就是响应式的
const vm = new Vue({data: { n : 0 } })
Vue的data是响应式的
体现在,如果修改vm.n,那么UI中的n就会做出响应
Vue2通过Object.defineProperty来实现数据响应式
2.Object.defineProperty存在问题
一般情况下,
Object.defineProperty(obj,'foo',{
value : 100
})
//函数参数列有:对象名,属性名,属性值
特殊情况1:data中不定义foo,在tamplate调用foo
new Vue({
data: {}, //这里没有定义foo
template: `
<div>{{foo}}</div> //这里又调用n
`
}).$mount("#app");
[Vue warn]: Property or method "foo" is not defined on the instance but referenced during render.
//此时控制台会输出一段警告,表明你没有定义foo但是渲染时却又调用
特殊情况2:
Vue只检查属性的第一层 { 这里面写了就行 }
data中不定义属性b,methods中对属性b进行操作
new Vue({
data: { //第一层
obj: { //第二层
a: 0 // obj.a 会被 Vue 监听 & 代理
// 此时不定义b
}
},
template: `
<div>
{{obj.b}} //这里调用obj.b
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
this.obj.b = 1; //请问,页面中会显示 1 吗?
}
}
}).$mount("#app");
//此时,控制台并不会报错。但是,点击button页面也不会有反应
//Vue没办法监听一开始不存在的obj.b
解决办法:
Vue.set(vm.someObject, 'price_one', 666)
this.$set(this.someObject,'price_two',999)
//两者等价
作用:
1.新增key
2.自动创建代理和监听(如果没有创建过)
3.触发UI更新(但不是立刻)
3.继续特殊情况: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' 吗?
// 等下,你为什么不用 this.array.push('d')
}
}
}).$mount("#app");
//点击之后毫无反应
//data中的数组等同于
{
{0:'a',1:'b',2:'c'}
}
//所以此时添加d,但是与"特殊情况1" 中相同,d没有下标,所以无法追加到数组中
问题来了:只能用Vue.set或者this.$set了吗?
methods: {
setD() {
this.$set(this.array,3,'d')
}
}
//这样确实可以运行,但是js操作数组时一般用push来追加元素
等下,你为什么不用 this.array.push('d')
methods: {
setD() {
this.array.push('d')
//console.log(this.array)
}
}
//成功了,此时控制台输出this.array
此时,数组的方法已经不是js中数组自带的方法,vue对它进行了升级
大致思路为(以push方法为例)
class VueArray extends Array{
push(...args){
const oldLength = this.length //this代表当前数组
super.push(...args)
console.log('你进行了push')
for(let i = oldLength ;i<this.length; i++){
Vue.set(this, i ,this[i])
//将每个新增的key都告诉Vue
}
}
}
4.查阅文档发现,Vue对如下几个方法都进行过了升级
//位置:数组更新检测-变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()