# Vue 数据响应式
# getter、setter
let obj = {
姓: "高",
名: "圆圆",
姓_名() {
return this.姓 + this.名;
},
get 姓名() {
return this.姓 + this.名;
},
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
}
};
console.log("需求一:" + obj.姓_名());
console.log("需求二:" + obj.姓名);
obj.姓名 = '高媛媛'
console.log(`需求三:姓 ${obj.姓},名 ${obj.名}`)
# Object.defineProperty()
该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。 可以给对象添加value属性,添加 getter/setter(用于对属性的读写进行监控)
var _xxx = 0
Object.defineProperty(obj,'xxx',{
get() {
return _xxx
},
set(v) {
_xxx = v
}
})
Object.defineProperty() 存在的问题
1、未定义就使用 Property or method "n" is not defined on the instance but referenced during render
new Vue({
data: {},
template: `
<div>{{n}}</div>
`
}).$mount("#app");
2、 Vue 只会检查第一层属性,无法监听一开始不存在的属性
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; //不会显示 1
Vue.set( this.obj, 'b' , 1)
this.$set( this.obj, 'b', 1)
console.log(Vue.set === this.$set) //作用相同
}
}
}).$mount("#app");
解决措施:
Vue.set 或 this.$set
# 变更方法
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
https://cn.vuejs.org/v2/guide/list.html?#%E5%8F%98%E6%9B%B4%E6%96%B9%E6%B3%95
测试题
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.a = 'a2'
app.obj.b = 'b'
最终span-a 中显示a2,span-b 中显示b
span-b 之所以会显示 b,是因为视图在显示 span-a 的 a2 时,顺便更新了 span-b。 因为视图更新其实是异步的。
- 当我们让 a 从 'a1' 变成 'a2' 时,Vue 会监听到这个变化,但是 Vue 并不能马上更新视图,因为 Vue 是使用 Object.defineProperty 这样的方式来监听变化的,监听到变化后会创建一个视图更新任务到任务队列里。(文档有写)
- 所以在视图更新之前,要先把余下的代码运行完才行,也就是会运行 b = 'b'。
- 等到视图更新的时候,由于 Vue 会去做 diff(文档有写),于是 Vue 就会发现 a 和 b 都变了,自然会去更新 span-a 和 span-b。
# 代理
https://codesandbox.io/s/bold-heyrovsky-8jcm2