总结
- Vue2数据响应式的实现是通过ES6的setter和getter这两个API还有Object.defineProperty函数来实现的,主要是new Vue后Vue对options内的data进行了一系列的操作,让data能够拥有响应式,
一、数据响应式是什么
-
你被打一拳你喊疼,那你就是响应式
-
当一个物体能对外界的刺激做出反应,它就是响应式的
-
Vue的data是响应式,Vue知道属性变了就能调用
render(data) -
UI =
render(data)
代码验证
const vm = new Vue({data:{ n : 0 }})
-
如果修改
vm.n,那么UI的n就会响应我 -
Vue2就是通过
Object.defineProperty实现数据响应式,你传给Vue一个data,Vue会把这个data做监听和代理的操作,以达到数据响应式的效果
二、getter/setter 怎么理解
-
用于对属性的读写进行监控(观察)
-
getter: 读取属性 -
setter:改写属性
代码实例
let obj = {
姓: "高",
名: "圆圆",
get 姓名() {
return this.姓 + this.名;
},
set 姓名(xxx) {
this.姓 = xxx[0];
this.名 = xxx.substring(1);
},
age: 18
};
console.log(obj2.姓名);// 高圆圆
obj3.姓名 = "刘诗诗";
console.log(`姓${obj3.姓},名${obj3.名}`); //姓刘,名诗诗
三、Object.defineProperty() 怎么理解
-
可以给对象添加属性Value
-
可以个对象添加
getter/setter -
可以给对象的属性进行代理
代理是什么
-
是一种设计模式,类似于房东、中介和租客的关系
-
为了对数据进行监控,监控能防止属性变了,但Vue不知道,这样就不能响应数据了
代码实例
// 需求:定义n的值,n小于0就不运行,n大于0则正常运行,要防止用户直接访问到数据
let data1 = proxy({data:myData}) //匿名的数据 不能被直接访问
function proxy({data}){ //
let value = data.n // 这里直接覆盖了data.n的值 也就是myData5的n
Object.defineProperty(data,'n'{
get(){
return value
},
set(newValue){
if(newValue<0)return
value = newValue
}
}) // 就加了上面几句话,就能监听data
const obj = {}
Object.defineProperty(obj,'n',{
get(){
return data.n
},
set(value){
if(value<0)return
data.n = value
}
})
return obj // obj就是代理
}
console.log(`${data1.n}`)
myData5.n = -1
console.log(`${data1.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`${data1.n},设置为 1 成功了`)
// let data1 = proxy({ data:myData })
// let vm = new Vue({data: myData})
// 几乎和Vue一样
四、数据响应式关于数组的处理
-
因为数组不能提前知道它的长度,大多数时候数组是需要进行增删改处理的
-
在把数组传给Vue时,Vue监听到了当时数组的key,后续增加的key用常规的方式并不具备数据响应的能力
解决方法
-
Vue给数组定义了一个重新封装拥有7个API的原型,这个原型是在数组的原型上增加的一层原型链,给开发者提供了数组的数据响应式功能
-
具体使用方法看一下文档即可了解列表渲染 — Vue.js (vuejs.org)
需要注意的Vue不能监测以下数组的变动
-
当你利用索引直接设置一个数组项时
-
当你修改数组的长度时
代码示例
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
- 一定要用Vue提供的7个API操作数组(
$set也行)
五、数据响应式关于对象的处理
- 假如你Vue的
data没有定义a数据,而你却使用了a数据,Vue就会报错
代码示例
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
如果需要添加响应式property
- 需要用到
Vue.set或者this.$set
代码示例
// Vue.set
Vue.set(vm.someObject, 'b', 2)
// this.set
this.$set(this.someObject,'b',2)
- 这两个方法是完全一样的用哪个都行