一、看以下代码
import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
const myData = {
n: 0
};
console.log(myData)
const vm = new Vue({
data: myData,
template: `<div>{{n}}
<button @click="add">+10</button></div>
`,
methods: {
add() {
// this.n+=10
myData.n += 10;
}
}
}).$mount("#app");
setTimeout(() => {
myData.n += 10;
console.log(myData);
console.log(vm);
}, 3000);
console.log(myData)
显示结果为
log得出的myData值为
可以看到n
从{n:0}
变成n:(...)
为什么???
二、getter
1.如何不用()获得姓名
看第一段代码
let obj1={
姓:"高",
名:"圆圆",
姓名(){
return this.姓+this.名;
},
age:18
}
console.log(obj1.姓名());//这里需要()
//输出:高圆圆
2.看第二段代码
let obj2={
姓:"高",
名:"圆圆",
get 姓名(){ //这里给了get
return this.姓+this.名;
},
age:18
}
console.log(obj2.姓名);//这里不需要()
//同样输出:高圆圆
总结:getter是不加括号的函数,获得某个值
三、setter
setter
设置值
let obj2={
姓:"高",
名:"圆圆",
get 姓名(){ //这里给了get
return this.姓+this.名;
},
set 姓名(xxx){
this.姓=xxx[0]
this.名=xxx.slice(1)
}
}
obj.姓名="赵丽颖"
console.log(`姓${obj.姓},名${obj.名}`);//这里不需要()
//输出:姓赵,名丽颖
打印出obj console.log(obj)
可以看到,obj有姓名:(...)
,姓名并不是我们自己设置的,这里说明的是我们可以对姓名进行读写,但是并不存在一个属性是姓名。同理,n也是如此
四、Object.defineProperty
直接在一个对象上定义一个新属性
Object.defineProperty(对象,定义的一个属性,{get(){},set(){}}
Object.defineProperty(obj,'xxx'}{
get(){
return _xxx
}
set(value){
_xxx=value
}}
五、代理和监听
1.代码一
let data1={}
Object.defineProperty(data1,'n',{
value:0
}
console.log(`${data1.n}`)
//输出:0
2.代码2:n不能小于0
let data2={}
data2._n=0//_n用来存储n的值
Object.defineProperty(data2,'n',{
get(){
return this._n
},
set(value){
if(value<0) return
this._n=value
}
})
console.log(`${data2.n}`)
data2.n=-1
console.log(`${data2.n}设置为-1失败`)
data2.n=1
console.log(`${data2.n}设置为1成功`)
//输出:0
0设置为-1失败
1设置为1成功
但是如果data._n被改变了怎么办?
3.代理
let data3=proxy({data:{n:0}})
function proxy({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(`${data3.n}`)
data3.n=-1
console.log(`${data3.n},设置-1失败`)
data3.n=1
console.log(`${data3.n},设置1成功`)
//输出:0
0设置为-1失败
1设置为1成功
通过改obj的值来改data的值,obj就是代理 但是如果直接操控myData的值也可以使n<0,看一下代码
let myData={n:0}
let data4=proxy({data:myData})//括号里是匿名对象,无法访问
console.log(`${data4.n}`)
myData.n=-1
console.log(`${data4.n},设置成功了吗`)
//输出:0
-1,设置成功了吗
从输出结果可以看到,可以直接通过myData使n<0 接下来,拦截用户直接修改myData的值
let myData5={n:0}
let data5=proxy2({data:myData5})
function proxy2({data}){
let value=data.n //保存最开始的n
delete data.n //这句话可以不写,因为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
}
//现在修改myDaya的值看看还能不能成功
console.log(`${data5.n}`)
myData5.n=-1
console.log(`${data5.n},设置为-1失败了`)
myData5.n=1
console.log(`${data5.n},设置为1成功了`)
//输出结果:0
0,设置为-1失败了
1,设置为1成功了
总结
Object.defineProperty
• 可以给对象添加属性value
• 可以给对象添加getter/setter
• getter/setter用于对属性的读写进行监控
代理
• 对myData对象的属性进行读写,但是全权由另一个对象来vm操控
• 所以vm就是myData的代理
let vm = new Vue({data:myData})
• 会让vm成为myData的代理
• 会对myData的属性进行监控
- 为什么要监控,为了防止myData属性发生了改变,但是vm不知道
- 知道了,就可以调用render(data)
- 所以,vue会对里面的data加监听,同时,新生成的对象会变成Vue的代理