首先我们知道,Vue
实现了双向绑定和响应依赖,当数据变化时,Vue
能够智能地计算出重新渲染组件的最小代价并应用到DOM
操作上。
我们还知道,Vue
对数组的更新检测和对对象的更改检测是有限制的。那么对Set
和Map
等常用的数据类型,Vue
的监测是否有效呢?如果无效,有没有弥补的方法?
下文的讲述将基于这个网页。结构很简单。
|
|
在浏览器里打开这个网页,打开控制台,输入app.arr.push(3)
。嗯,一切正常。接下来试试集合。
因为v-for
指令不能直接用于集合,集合的列表渲染可以这样写——
<p>集合的列表渲染</p>
<ul>
//使用扩展运算符,将集合转成数组。
//用Array.from(set)也可以。
<li v-for="item in [...set]">{{ item }}</li>
</ul>
顺便也试试集合的条件渲染——
<p>集合的条件渲染</p>
<div v-if="set.has(1)">现在集合里有1了~</div>
<div v-else>集合里没有1</div>
还有集合的计算属性渲染——
<p>相关依赖是集合的计算属性渲染</p>
<ul>
<li v-for="item in [...doubleSetComputed]">{{ item }}</li>
</ul>
......
computed: {
......
doubleSetComputed() {
return new Set([...this.set].map(item => item*2));
}
}
修改网页,再打开控制台,输入app.set.add(1)
。不出所料,没动静。所幸Vue
提供了一个叫做forceUpdate()的方法。
再输入app.$forceUpdate()
。集合的列表渲染和条件渲染都正常了,但是计算属性纹丝不动,为啥呢?Vue
的文档做得是真心好,也提供了相关答案:计算属性的缓存-vs-method-方法。简单来说,集合不是Vue
所认为的响应式依赖,计算属性在这里失灵了。
解决方法也不难,这里不用计算属性,改用method
方法——
<p>相关依赖是集合的method方法渲染</p>
<ul>
<li v-for="item in [...doubleSetMethods()]">{{ item }}</li>
</ul>
methods: {
doubleSetMethods() {
return new Set([...this.set].map(item => item*2));
}
}
再次使用app.$forceUpdate()
。成功!
文章到这里接近结束了。篇末做一个总结——
- 对
Set
等数据结构,Vue
无法做到响应式依赖。 - 可以使用
forceUpdate()
强制渲染。 - 如果相关依赖是
Set
,请使用method
方法而不是计算属性。
再贴上和数据更新检测相关的几篇文章供大家参考——
Vue爬坑日记,数组数据的更新检测
vue.js中$set与数组更新
Vue.set( target, key, value )