在使用Vue进行开发时,一旦页面上展示的数据在js中进行了更新,那么并不需要开发者编写有关渲染的代码,Vue会自动将页面对应的数据更新。因为Vue底层对实例化时声明的数据(属性)都进行了监听和代理,即当数据变化时,Vue会立刻监听到变化,并调用渲染操作。
通俗来讲就是当修改vm的属性,那么页面会根据修改的内容自动改变。
使用Object.defineProperty(obj , 'n' , {....})监听
//一个简单的例子
new Vue(
data: {
obj: {
a: 0
}
}
template: `
<div>
{{obj.b}} //如果不加Vue.set或者this.$set,定义的是a,打印的是b。但不会报错,只会显示空白
</div>
`,
methods: {
setB() {
Vue.set(this.obj, 'b', 1) //与下面一句等价
this.$set(this.obj, 'b', 1) //加了之后新增b,并且把1赋值给b,会自动更新页面
}
})
会有两个bug:
- data里面如果啥都没写,Vue会给出一个警告,不会显示null或者undefined,页面会显示空白。
- 如果写了一个属性a,但是后续改了一个属性b。那么vue不会去监听这个属性b,但是不会报错。vue之后检查第一层属性,只检查a。 解决方法:
- 把key都声明好,后面不再添加新的属性。
- 用
Vue.set或者this.$set添加属性。会直接新增这个key;如果没有创建代理和监听,Vue.set会自动创建代理和监听(this.set。Vue将数组默认的方法篡改了。方便数组的增删。原理也是用Object.defineProperty的set方法。
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse() 练习题1
//html代码
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
//js代码
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.a = 'a2'
span-a输出a2,span-b显示空白
练习2
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
//js代码
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.b = 'b'
span-a显示a,span-b显示空白
练习3
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
//js
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.a = 'a2'
app.obj.b = 'b'
span-a显示a2,span-b显示b //异步更新UI的坑(后续再填)