【问题标题】:Vue 2 mutating a data property inside a v-for causes infinite loops / problemsVue 2 在 v-for 中改变数据属性会导致无限循环/问题
【发布时间】:2017-10-31 20:16:56
【问题描述】:

虽然我在文档中找不到,但改变数据数组属性似乎不是一个好主意,即使它没有被渲染到视图中。

看到这个小提琴:https://jsfiddle.net/078v5142/3/

我需要减少conditionalSet。我在每个 v-for 循环上使用 pop() 来检查索引的条件。我不能使用计算属性,因为我需要传递索引。

我也不能只复制conditionalSet 数组,因为在设置和弹出条件时需要对其进行跟踪。

这是我面临的一个大大简化的问题。

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js! I do not like loops, all that much.',
    imageSet: [
     'a','b','c','d','e','f','g', 'h', 'i', 'j'
    ],
    conditionalSet: [1,2]
  },
  methods: {
    doShow(index){
     if(this.someInnerConditionThatsNotRenderedOut()){
       if( index === 1 || index === 4 || index === 5 || index === 6){
         this.conditionalSet.pop(); // <-- this is the problem, but how to I track?
         return true;
       }
     }
     console.log('I should no show index 5 and index 6')
    },
    someInnerConditionThatsNotRenderedOut(){
     return true //comment this out. No error.
     return this.conditionalSet.length > 0
    }
  }
})

【问题讨论】:

    标签: javascript vuejs2


    【解决方案1】:

    简短的回答

    长话短说,我认为您可以(并且应该)使用计算属性来显示过滤后的列表。我不是 100% 清楚你在你的例子中试图实现什么,但希望这个小提琴能给你一个指针:https://jsfiddle.net/dtchqpjd/ 如果你在控制台运行时查看它,你将能够看到逻辑是如何平移的出去。

    更长的答案

    这个问题实际上是由三件事共同引起的:

    • 您的doShow 函数有副作用。
    • 该副作用与数据属性有关,VueJS 会“监视”该属性。
    • 该数据属性是一个数组,您需要“获取”它才能修改/弹出。

    VueJS 有一个 reactivity system 来监视数据,并在数据发生变化时确定这将对 DOM 产生的影响。这允许它有效地更新 DOM 以响应数据更改,而无需在每次发生更改时完全重新创建 DOM。

    在这种情况下,VueJS 知道以下内容:

    • 您将获得conditionalSet 属性。您必须这样做才能调用 pop 方法。但是 Vue 不知道你对返回的值做了什么。
    • 您可以通过调用 pop 方法更改conditionalSet 属性。

    因为你 getset 属性,VueJS 假定 doShow 函数返回的结果是陈旧的,因此重新评估它,然后你得到一个无限循环。它看不到您只是“得到”它,因为您想“弹出”它!

    当你在计算属性中执行过滤和修改时,你可以避免混淆 VueJS(和无限循环),因为它可以看到结果是稳定的,不需要重新计算。它也恰好是更清晰的代码,因为逻辑都在一个地方。但是,您的计算属性仍然有一个副作用,如果我对您尝试做的事情有更多了解的话,也可以避免。

    一个小插图

    为了说明正在发生的事情,here's a slight modification to your fiddle,我在其中对数组进行了单独的(Vue 未知)引用。当我使用该引用来调用“pop”时,您不会得到无限循环:Vue 仍然可以看到我们已经更改了数组,但是因为我们没有“得到”它,所以它不会假设该函数的输出现在已过时。取消注释刚刚“获取”数组的调用,问题又回来了:Vue 认为它需要重新评估函数。

    有趣的是,Vue 似乎并没有查看依赖项的顺序:“get”然后“set”或“set”然后“get”都没有关系。只是你做了这两个事实导致循环依赖 - 它们被添加为依赖并导致对队列的重新评估。

    注释掉 return true 语句可以避免无限循环,因为它可以防止数组被不断“弹出”:一旦数组被弹出两次,您的 someInnerConditionThatsNotRenderedOut 函数返回 false,并且可能出现无限循环被剪短了。

    【讨论】:

    • 只需阅读您对需要保留
    • 更新了小提琴。您觉得在渲染过程中需要弹出数组这一事实仍然存在很大问题,但我对您的具体问题知之甚少,无法弄清楚该怎么做。无论如何,希望它有所帮助。
    • 啊,关键是你的 beforeMount 钩子并消除了反应性。聪明的。我将重新考虑我的“真正问题”,但是您在这里说明的内容已经解决了。感谢您的宝贵时间。
    • jsfiddle.net/xbcn6hpw/6 vue 通过 v-for 将参数传递到 v-if 失败的简单示例。但我需要这个功能......
    【解决方案2】:

    你只是想得很努力;)

    想象一个计算方法,它过滤您的 imageSet 并返回您想要的结果,然后您的 v-for 对其进行操作。

    你的一些变化: https://jsfiddle.net/5dbakawb/

    【讨论】:

    • 不幸的是,我无法删除循环内的
    • @Simon 所以,不要删除它 :) 我这样做是为了让它更简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    相关资源
    最近更新 更多