什么是vue数据响应式
数据改变,UI页面做出响应。
当修改 Vue 实例中的 data 属性时,UI页面中的 data 会做出响应,Vue 是通过Object.defineProperty来实现数据响应的。
const vm = new Vue ({data:myDate})
Vue中如何实现数据响应式
1.通过getter和setter修改对象属性实现数据响应
getter:
//修改姓名
let obj3 = {
姓: "huang",
名: "rui",
age: 23,
get 姓名() {
return this.姓 + this.名;
},
set 姓名(xxx) {
//设置姓名为obj3.姓名
this.姓 = xxx[0];
this.名 = xxx.substring(1);
}
};
obj3.姓名 = "胡歌";
console.log(`姓名:${obj3.姓}${obj3.名}`);
setter:
let obj3 = {
姓:"高",
名:"圆圆",
get 姓名(){
return this.姓 + this.名;
}
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.substring(1)
}}
obj3.姓名 = "彭于晏"
console.log(`打印三: 姓${obj3.姓},名${obj3.名}`) //打印三:姓:彭,名:于晏
总结: setter就是接受一个参数的函数 用 = xxx 这样的形式触发,来改变里面的值
2.定义完成的对象通过Object.defineProperty(obj,'n',{value:4})添加属性
接上面,我们再使用set和get的时候都是在声明的时候就直接使用的,但是我想声明之后再使用怎么办,这就用到Object.defineProperty()了
Object.defineProperty()第一个参数是告诉它,定义再那个对象上,第二个参数就是要定义个什么东西,然后就能写了
var _xxx = 0
Object.defineProperty(obj3,"xxx",{
get(){
return _xxx
},
set(value){
_xxx = value
}
})
这里需要注意定义的xxx是不存在的所以你用get传是不行的,而且会死循环(因为你在调用xxx的时候就会触发,无限循环),所以需要重新定义一个值用来传。
但是这里有一个问题,我们可以通过直接改变全局变量_xxx来改变里面的值,这不是我们想看到的,那么如何解决这个问题呢?
那就需要一个代理了
let data1 = proxy({data:{n:0}}) // 括号里面是匿名对象,所以根本无法访问
function proxy({data}){
conost obj = {}
Object.defineProperty(obj,"n",{
get(){
return data.n
}
set(value){
if(value<0)return
data.n = value
}
})
return obj //这就是代理
}
这样你动我obj的n我就会去设置data的n,obj就是一个代理,这样你就不能擅自修改我的对象数据,你只能通过obj代理来修改?
错! 我还是能修改
如果你那个匿名函数我用对象给你呢
let myData5 = {n:0}
let data1 = proxy({data:myData5})
那我只要修改myData5 还是能改你的数据,这时候就不能只靠代理了,还需要监听,就算你改了也没用,我监听你
let myData5 = {n:0}
let data = proxy({data:myData5})
function proxy({data /*这里用了解构赋值*/}){
let value = data.n
delete data.n //这一句可以不写因为下面已经覆盖了原先的n
Object.defineProperty(data,"n",{ //这里挂载的对象就是参数data
get(){
return value
}
set(newvalue){
if(newvalue<0)return
value = newvalue
}
})
//上面这几句,就会监听data
conost obj = {}
Object.defineProperty(obj,"n",{
get(){
return data.n
}
set(value){
if(value<0)return
data.n = value
}
})
return obj //这就是代理
}
上面的方法就是把原先的数据复制一遍,再删掉用新数据来填补,这样你就不能通过对象修改我的数据
这就是响应式,vue监听了这个数值,vue 会让 vm 成为 myData 的代理,vue 会对 myData 的所有属性进行监控,当数值发生改变的时候,vue就重新渲染
而原理是把一个普通的 JavaScript 对象传入 Vue 实例作为data选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter
总结
Vue会让vm成为myData的代理(proxy)
所以你对vm的操作就相当于对myData进行的操作,同时你还能通过this来访问到vm,因为this就是vm,vm就是myData的代理所以再vue中你可以通过this来读取data的值。
然后再通过上面说过的监听来对myData的所有属性进行监控
为什么要监控?
为了防止myData的属性变了,vm还不知道,那知道了又如何?知道了属性变了就能调用render(data)了呀让ui自动刷新了啊,这就是响应啊
Vue 的 Data 的 bug