Vue2.6新增了observable函数,用于生成一个响应式对象。网上有很多关于小项目中使用Vue.observable代替Vuex的文章,但我试了一下不使用observable而是直接新建普通对象好像也能实现数据的同步(?),所以又回头看了一下Vue的Observer。
关于observable函数,Vue官方文档是这样描述的:
在 Vue 2.x 中,被传入的对象会直接被
Vue.observable
变更,所以如这里展示的,它和被返回的对象是同一个对象。在 Vue 3.x 中,则会返回一个可响应的代理,而对源对象直接进行变更仍然是不可响应的。因此,为了向前兼容,我们推荐始终操作使用Vue.observable
返回的对象,而不是传入源对象。
这个响应式对象即Observer对象。Observer对象主要用于触发DOM的更新。
在Vue2中,所有在data中声明的对象以及computed中的属性的依赖项,Vue都会将其包装成Observer对象,因此我们平常即使是新建一个普通对象赋值到data中的数据上,DOM也会更新,因此看不出Observer的效果,但我们可以绕过Vue的包装这一层。在深入响应式原理这一节中,我们知道,如果直接往嵌套对象添加一个属性Vue是监测不到的。尝试如下代码:
<template>
<div>
<div>{{ state }}</div>
<button @click="onClick">add</button>
</div>
</template>
<script>
import Vue from "vue";
export default {
name: "test",
data() {
return {
state: {
a: 1,
b: 2,
},
};
},
watch: {
state: {
handler: (val, oldVal) => {
console.log(val);
},
deep: true,
},
},
created() {
let state1 = {
a: 1,
b: 2,
};
this.state.c = state1;
console.log(this.state);
},
methods: {
onClick() {
this.state.c.a += 1;
console.log(this.state);
},
},
};
</script>
当我们点击按钮后,可以看到界面是不会发生改变的,但控制台输出的内容可以看到,state.c实际上已经被改变了。因为state.c不是一个Observer对象。如果我们在创建state1的时候将其创建为一个响应式对象:let state1 = Vue.observable({ a:1, b:2 })
,此时点击按钮可以看到界面更新了。但是此时watch中的console.log依然没有输出,点开控制台的state对象可以看到,此时state.c已经是一个Observer对象了,但是由于c属性是后加进去的,state本身并没有对其的监测,没有相对应的getter,setter,因此此时watch是监测不到的。
所以说如果不涉及DOM更新或者需要watch的情况的话,使用普通对象也是可以的;但大部分情况下建议使用observable新建响应式对象。
网友评论