ES6中的getter setter
let Person = {
set name (name) {
console.log("setter");
this._name = name;
}
get name () {
console.log("getter");
return this._name;
}
}
通过getter和setter设置一个伪属性,利用不同名的变量模拟对于属性的操作
注意不要写
get name(){
return this.name
}
这种调用方式会100%爆栈
Object.defineProperty
MDN连接
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
const _xxx = 0;
Object.defineProperty(obj3, "xxx", {
get() {
return _xxx;
},
set(value) {
// 可以通过额外的操作给变量的取值和赋值进行监控
_xxx = value;
},
});
小结:
Object.defineProperty
-
可以给对象添加属性 value
-
可以给对象添加 getter/setter
-
getter/setter 在定义的时候用于对属性的读写进行监控
代理(设计模式)
以Vue的声明为例const vm =new Vue(Data)
对Vue的构造对象的Data属性读写,全权由另一个对象Vue的实例vm来控制,通过vm.n 来操作 Data.n
vm = new Vue({data:myData})
- vm 成为 myData 的代理(proxy),对myData 的所有属性进行监控
- 为什么要监控,为防止 myData 的属性变了,vm 不知道
- vm 捕获到变化就可以重新渲染 UI = render(data)
示意图
什么是响应式
-
基本思想 能够对外界的对象改变做出反应,就可以称作响应式。例如Vue的数据响应,网页的响应式布局
-
Vue的响应式
const vm = new Vue({data:{n:0}})
修改data中的n,那么对应UI中显示的n就会变化
data中的bug
如果属性一开始就不存在,就不会被监听
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");
解决方法
使用 Vue.set 或 this.$set
作用:
- 在data中新增 key
- 自动创建代理和监听(如果没创建过)
- 触发 UI 更新(不会立刻更新,副作用)
举例:this.$set(this.object,"b",100)
new Vue({
data: {
obj: {
a: 0, // obj.a 会被 Vue 监听 & 代理
},
},
template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
Vue.set(this.obj, "b", 1);
// this.$set(this.obj, 'b', 1)
},
},
}).$mount("#app");
变异方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()pop()shift()unshift()splice()sort()reverse()
总结
对象中新增的 key
Vue 没有办法事先监听和代理 要使用 set 来新增 key,来创建监听和代理,更新 UI 最好提前把属性都写出来,不要新增key
数组中新增的 key
也可以用 set 来新增 key,不会创建监听和代理,会更新 UI