Vue是否支持Map和Set数据类型的反应性?

时间:2016-05-10 05:42:33

标签: vue.js

Vue.js的文档提到了普通Javascript对象的智能自动更改跟踪

  

当您将纯JavaScript对象作为其数据选项传递给Vue实例时,Vue.js将遍历其所有属性并使用Object.defineProperty将它们转换为getter / setter。

由于Javascript的MapSet数据类型旨在与其内置get / set方法一起使用,因此如何让Vue跟踪调用(以及因此,改变了Map s和Set s?

的内部状态

3 个答案:

答案 0 :(得分:22)

Vue.js不支持对MapSet数据类型的反应(但是?)。

feature ticket有一些讨论和解决方法(由用户" inca"):

  

Vue无法观察到集合和地图。为了使用那些 -   在v-for中,或在计算属性,方法,观察者,   模板表达式等 - 您需要创建一个可序列化的副本   这个结构并将其暴露给Vue。这是一个天真的例子   使用一个简单的计数器为Vue提供Set的信息   更新:

data() {
  mySetChangeTracker: 1,
  mySet: new Set(),
},

computed: {
  mySetAsList() { 
    // By using `mySetChangeTracker` we tell Vue that this property depends on it,
    // so it gets re-evaluated whenever `mySetChangeTracker` changes
    return this.mySetChangeTracker && Array.from(this.mySet);
  },
},

methods: {
  add(item) {
    this.mySet.add(item);
    // Trigger Vue updates
    this.mySetChangeTracker += 1;
  }
}
     

这说明了一种有点hacky但100%有效的制作方法   不可观察的数据反应。在现实世界的情况下,我最终还是结束了   使用集合/地图的序列化版本(例如,您可能想要   将集合/映射的修改版本存储在localstorage中,从而   无论如何序列化它们,所以没有涉及人工计数器/黑客。

答案 1 :(得分:7)

Vue 3

是的。

Vue 3文档涵盖了Reactivity in depthBasic Reactivity APIs

另外还有“反应性”和“参考”四种。在使用Vue 3和ES6编码6个月以上之后,我仍在尝试寻找适合自己的使用模式。主要问题是使用Reactive还是Reference

参考

Reference是简单的方法。例如,computed返回的就是这个。它是一个人的JavaScript值的反应式版本,例如MapSet

有一个陷阱。如果一个人在自己的JavaScript中使用Reference,则需要添加一个.value来取消对该值的引用。在模板HTML中使用它不需要添加。这使Reference非常适合面向UI的事物,而对于内部编程则不那么理想。

我目前将Ref后缀添加到提供Reference的任何值或函数的名称中。这就是我。如果同时使用ReferenceReactive很容易感到困惑(这里有TypeScript会有所帮助)。

反应性

Reactive用于类似Map的用途。可以将其初始化为:

const rve = reactive( new Map() )

访问此类不需要.value。但是,似乎Reactive没有枚举方法(例如.entries())可以像Map一样使用。因此,它似乎针对您知道对象键的用例。但这可能会改变。

我希望Reactive的发展方向是可以以1:1替代ES Map。这对我来说很容易:Reactive用于Map,其余Reference

我也希望名称可以更改,以使它们更接近。 RMap很好-也许我会做一个(从Reactive派生并添加枚举方法)。

摘要

对于Vue 3,最有力的答案是“是”。

但是,开发人员指南可以变得更加简单明了,明确指出选择ReferenceReactive的逻辑是什么,例如。它们的运行时优缺点,而无需阅读各种博客文章。


编辑:我目前的倾向是Ref,但我试图在代码中尽早展开反应性,导致.value中只有一个computed

答案 2 :(得分:1)

据我所知,Vue的反应性跟踪分配。如果您在集合上执行分配,则它应该跟踪反应性,例如:

methods: {
  add(item) {
    this.mySet = new Set(this.mySet.add(item));
  }
}

这为您提供了更简洁的代码,但存在一个明显的问题:性能。

只需根据需要选择解决方案即可:)