Vue: v-for 支持更多的集合数据类型

创建于 2016-02-28  ·  39评论  ·  资料来源: vuejs/vue

在某些情况下,普通对象不是最佳选择。 我试图通过v-for渲染Map对象,但似乎Vue目前不支持它。 (这里有一个帖子在论坛的帮助线程创建的我。)

希望Vue可以提供for ... of在语法v-for以上的数据类型等来迭代MapSet

例如:

const map = new Map();
map.set('key1', 'val1');
map.set('key2', 'val2');

我们可以这样渲染map

<ul>
    <li v-for="[key, val] of map">{{key}} - {{val}}</li>
</ul>
feature request

最有用的评论

能够在循环中迭代迭代器很重要。 这似乎是显而易见的。 这是语言的一个基本特征。

支持它的理由是:

1) 迭代器、映射和集合都是有效的 ES6。 拒绝支持它们意味着将自己限制在 ES5 上,随着时间的推移,这是一个越来越不合理的决定。
2) 我正在构建一个应用程序,它的内部数据存储在 Maps 和 Sets 中。 我现在不需要让它们对 UI 可用,而是需要手动保持两者之间的数据同步,或者编写样板并将其导入到我的模板中,以便在需要数据时进行转换。 这正是 Vue 想要避免的。

所有39条评论

https://github.com/vuejs/vue/issues/1319的副本

@wenLiangcan ,你可以使用这样的东西:

<ul>
    <li v-for="[key, val] of get(map)">{{key}} - {{val}}</li>
</ul>

其中get()是您的函数。

哈哈! 类似的问题一直存在,并且人们坚持认为他们不能很好地证明实施人们想要使用它这是一个理由我还可以列出大量已关闭的问题 xD。 我还发现了一个可以很好地证明用例的方法,并且在涉及映射顺序时参考了 es6 规范 -> 仍然关闭。

人们想要使用一个特性,不仅仅是它本身,一个可以证明拥有这样一个特性的必要性的论据,有必要权衡添加这样一个特性的成本和收益(正在解决什么问题)

是的,但人们用来解决问题的论点仍然无效或至少对所有用例都无效,例如 elipen 的例子,他很好地证明了他的用例,正如我上面提到的

如果你想讨论一个特定的问题,请链接到它。

另外,这个功能问题是开放的。 为同一个请求打开多个问题是没有意义的。

能够在循环中迭代迭代器很重要。 这似乎是显而易见的。 这是语言的一个基本特征。

支持它的理由是:

1) 迭代器、映射和集合都是有效的 ES6。 拒绝支持它们意味着将自己限制在 ES5 上,随着时间的推移,这是一个越来越不合理的决定。
2) 我正在构建一个应用程序,它的内部数据存储在 Maps 和 Sets 中。 我现在不需要让它们对 UI 可用,而是需要手动保持两者之间的数据同步,或者编写样板并将其导入到我的模板中,以便在需要数据时进行转换。 这正是 Vue 想要避免的。

由于#1319 已关闭,因此值得在此重申当前的决定。 简而言之,该功能的实现并非微不足道(在观察机制级别),因此它不是关于证明用例的合理性,而是关于工作量和权衡。

我也非常感谢这个功能。 另一方面,如果观察 ES6 数据类型变得非常糟糕,或者,例如,损害性能或其他品质,那么当前没有使用 Vue 的 Maps 和 Sets 的人可能不会欣赏这种变化。

我想现在在计算函数中使用

有什么解决办法吗?

小更新,如果/当 Vue 决定放弃“旧版”浏览器并使用Proxy而不是set / get移动到 Evergreen 浏览器时,就会出现这种情况。

@alexsandro-xpt,只需使用返回Array.from(yourDataSet)的计算函数。

@nickmessing我尝试使用 Map,但不起作用。
计算出的数组长度值始终为 0。

由于缺乏反应性,仅Array.from可能不是您想要的解决方案(对yourDataSet更改不会传播到 Vue)。

如前所述,Vue 无法观察到 Sets 和 Maps。 为了在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;
  }
}

这说明了一种使不可观察数据具有反应性的有点笨拙但 100% 的工作方法。 尽管如此,在现实世界的情况下,我最终得到了 Sets/Maps 的序列化版本(例如,您可能希望将修改过的 set/maps 版本存储在 localstorage 中,因此无论如何都将它们序列化),因此不涉及人工计数器/hacks。

我个人认为这是一个公平的问题解决方案,但它绝对值得一些官方文档 - 否则不可能证明这是处理 Vue 内部结构的非黑客方式。

@alexsandro-xpt,抱歉,我错了,计算会像@inca所说的那样笨拙的解决方案是将$forceUpdate与方法一起使用,这是一个示例小提琴

谢谢@nickmessing@inca ,这对我的new Map()很好用!!

现在,当您在“Map”上执行“v-for”时,v-for 就好像它收到了一个空数组一样。

不管关于是否/如何支持 Maps 和 Sets 的扩展讨论的结果,如果 Vue 简单地警告“尚未支持 Maps 和 Sets -- 见https://github .com/vuejs/vue/issues/2410 ”。

是的,谷歌搜索这个功能给我带来了这张票(在与 Vue.set 的一些烦人的混淆之后)

👍 这个应该在 v-for 文档里!

确实,应该在 v-for 文档中!

/cc @chrisvfritz让我们尝试在v-for (API 和列表呈现部分)的文档中添加有关对这些类型的支持的注释 - 我还将在 2.5 中查看它们。

@yyx990803我想知道控制台警告是否会更好,因为这会立即告诉人们出了什么问题,而无需搜索解决方案。

我们在文档中也已经非常明确地说明了我们_do_ 支持哪些类型, MapSet不在其中。 我绝对可以看到为什么人们可能_希望_所有可迭代对象都可以与v-for一起使用的论点,但我认为我们目前没有给读者任何期望他们会这样做的理由。

我不太明白反对添加对Set支持的论点。

Set本身可以被干净地填充,除非我遗漏了一些东西,似乎 Vue 为数组添加反应性的方法可以很容易地扩展到集合。 我们只需要包装.add().clear().delete()

我最好的猜测(如果我错了,请纠正/抱歉):最棘手的部分是包装一个Set构造函数,它接受一个可迭代对象。 我不知道如何将 iterable 变成可观察的,因为在它的一般形式中,它只是一个没有可引用状态的函数(即next )(以基于生成器的迭代器为例)。

为什么我们需要包装构造函数? 我们不会将预先存在的 Sets 传递给 Vue 吗?

根据规范Set构造函数立即贯穿整个迭代器,有效地保留了迭代器返回的唯一项的浅表副本。 一旦你有了一个Set实例,它是否是从迭代器创建的就不重要了。

在这方面,从迭代器创建的Set应该与从迭代器(通过Array.from() )创建的数组没有区别,Vue 已经支持。

您可以使用不可变的 Maps/sets/ 任何数据结构并允许与它们进行反应,但这仅仅是因为整个块引用发生了变化。 您可以通过渲染函数或计算生成的数组来渲染它们(越早性能越好,因为它跳过数组的创建......)。 但是可变数据结构,除非你找到一种方法来手动通知 Vue 特定的更改,否则这将只是自制你自己的解决方案。

那不好。 你不能这样做

@文亮灿

var map = new Map()
  map.set('key1','Test1')
  map.set('key2','Test2')
        <div class="file-size">{{value}}</div>
 </div>

不,它不会显示在页面上

热衷于支持这一点:)

我也是

未来有计划增加支持吗? Vue 不支持 Map 和 Set 是否有技术原因?

Vue.set 方法在普通对象上的当前问题是,当将属性添加到对象时,它会触发太多订阅者。 实际上,当只添加一个属性时,所有属性的所有订阅者都会被触发。

当像集合这样的地图包含百分之一的键时,视图的性能会受到严重影响。 例如,在我的项目中,当使用 Vue.set 操作将一个元素添加到地图时,会触发数千个订阅者:

Vue.set(state.items, itemId, item); // where items is a plain object.

当我深入查看 Vue.js 代码时,我可以看到问题出在哪里。 触发的依赖是对象的依赖,也就是说如果对象每个key都有一个属性,那么只要添加一个key就会触发所有key的所有依赖。

因此,使用普通对象来模拟地图看起来并不是正确的解决方案,因此在 vue 中支持地图对于大量项目来说是非常受欢迎的。

有没有关于未来计划的消息,可能还有关于原生Map/Set支持的消息?

这篇文章详细介绍了 2.6 中即将推出的支持 - 但我所看到的官方路线图中没有任何相关内容?

https://medium.com/@alberto.park/the -status-of-javascript-libraries-frameworks-2018-beyond-3a5a7cae7513

“当前最新的内核是 2.5.x。下一个次要版本 (v2.6),将支持本机 ESM 导入、改进的异步错误处理、'v-for' 指令的迭代器等等。”

不知道他们从哪里得到这些信息?

在调试 Vue 在Set数据对象上的行为时发现了这个问题。 :思维:

对于像我这样想知道路线图的人,Evan You 在这段视频中说 Map 和 Set 支持“可能”在 2.6 中推出,但那是在 5 月份,所以我只知道这些。

@yyx990803不幸的是,跟踪器中的这个问题被标记为已关闭,特别是如果您正在考虑在不久的将来添加支持。 我们可以在哪里跟踪此功能的进展? 某处还有其他问题吗?

只是为了争论而想知道,也许我做错了,但是既然您可以使用Mutation Methods跟踪数组突变,那么您就不能只跟踪一个对象的数组并在逻辑上是完整的吗? 您不会在 Map 中实现所有相同的功能,但是您想要的功能很容易解决,特别是如果您使用诸如 _ 或 lodash 之类的东西。

很遗憾,但在团队添加此内容之前,我们可能不得不使用替代数据结构

只是想补充一下,我们打算将 Map 用于我们的数据结构,然后由于缺乏第一方支持而决定反对。

这是为 vue.js v3.0 计划的。
比较: https :

现在在 Vue3 中是否支持(即反应式MapSet )?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

aviggngyv picture aviggngyv  ·  3评论

paulpflug picture paulpflug  ·  3评论

franciscolourenco picture franciscolourenco  ·  3评论

bdedardel picture bdedardel  ·  3评论

wufeng87 picture wufeng87  ·  3评论