如何改变基于Vue“prop”计算的数组?

Posted

技术标签:

【中文标题】如何改变基于Vue“prop”计算的数组?【英文标题】:How to mutate the array which has been computed based on Vue "prop"? 【发布时间】:2020-08-30 16:51:15 【问题描述】:

来自 Vue 文档:

prop 作为需要转换的原始值传入。在 在这种情况下,最好使用 prop 定义一个计算属性 价值。

Source

如果这个“道具”是对象数组怎么办?我试图根据文档将其转换为计算数组。那怎么变异呢?

在下面的示例中,组件接受项目数组Array< ID: string, lettering: string; >。 组件为每个项目呈现按钮。

    当我们点击按钮时,它必须改变颜色。 如果我们再次单击相同的按钮,它必须返回到初始状态。

Fiddle

<template>
  <div>
    <button  
      v-for="(item, index) in selectableItems"
      :key="`BUTTON-$item.ID`"
      :class=" selected: item.selected "
       @click="() => onButtonClicked(item, index) "
    >  item.lettering 
    </button>
  </div>  
</template>

我从items 计算selectableItems。除了 item 的属性之外,selectableItems 还具有属性 selected

export default 
  name: "HelloWorld",
  props: 
    items: Array
  ,
  computed: 
    selectableItems: function () 
      const selectableItems = [];
      this.items.forEach((item) => 
        selectableItems.push(
          ID: item.ID,
          lettering: item.lettering,
          selected: false
        );
      );
      return selectableItems;
    
  ,
  methods: 
    onButtonClicked: function(item, index) 
      if (item.selected) 
        this.selectableItems[index].selected = false;
       else 
        this.selectableItems[index].selected = true;
      
      console.log(this.selectableItems);
    
  
;

目前,Vue 不会重新渲染按钮。

我知道 getter 的 mutate 使用不当。 但是我应该如何改变数组呢?

禁解

不允许通过props 而不是 ID: string, lettering: string; 传递 ID: string, lettering: string; selected: boolean; ID: string, lettering: string; 是纯模型,一定不知道UI。 selected: boolean; 仅用于 UI。

【问题讨论】:

您的解决方案将不起作用,因为您尝试操作计算的道具,该道具在重新计算时将被简单地覆盖。您需要将元素的选定状态存储为数据,以使其正常工作。如果你的数组中有不变的索引,你可以使用这些。或者你在你的 props 上创建一个观察者,并将 props 中给出的所有数据存储为你的本地数据,并在更改时不断更新它 @FrankProvost,感谢您的评论。 “您需要将元素的选定状态存储为数据,以使其正常工作。” - 但如何?从 Vue API 的角度来看,这并不明显。 【参考方案1】:

这是 jsfiddle https://jsfiddle.net/hgvajn5t/ 中的一个简单示例

由于时间紧迫,我跳过了创建两个组件,实际上将数据作为道具向下传递。

关键是在数据中定义您选择的按钮

data () 
    return 
      selectedItems: []
    
,

第二部分是存储哪些项目被选中,哪些没有被选中

onButtonClicked: function(item)
  let index = this.selectedItems.indexOf(item.ID)
  if (index > -1) 
    this.selectedItems.splice(index, 1)
   else 
    this.selectedItems.push(item.ID)
  

onButtonClicked 将项目作为输入接收并检查它是否存在于您的 selectedItems 中 - 如果存在,它将被删除,否则将被添加

最后一部分是改变你的绑定来设置选择的类

:class=" selected: selectedItems.indexOf(item.ID) > -1 "

再次在这里 - 只需检查它是否是 selectItems 的一部分

然后您可以删除计算属性并简单地使用道具循环遍历元素。

重要提示:这仅在您的项目 ID 值是唯一的情况下才有效。

关于这个的一些一般性想法:当你刚接触 vue 时,这个概念可能有点难以理解,因为对于简单的选择状态来说,它似乎非常复杂。这对于我给出的解决方案来说可能是正确的——但总的来说,它在很大程度上取决于你如何构建你的 UI。这一切的主要原因是你不应该直接操纵道具。使用计算道具来增强它们是好的 - 操纵计算道具同样糟糕。如果您需要当前组件之外的选择状态,您将需要考虑使用事件向父级(数据来自哪里)发出对按钮的点击,并直接在那里更改选择状态。然后它将直接通过 props 传递。这是一种更“自然”的方式,因为您可以操纵单一事实来源,而不是在另一个屏幕中保存有关项目的附加信息。

【讨论】:

感谢您的解释!

以上是关于如何改变基于Vue“prop”计算的数组?的主要内容,如果未能解决你的问题,请参考以下文章

避免在可重用组件中直接改变 prop

VueJs 组件的 Prop 相关计算属性对对象数组 Prop 更改没有反应

Vue警告避免改变道具“taskToEdit”

Vue 2 + TypeScript:避免直接改变 Prop - 在带有 vue-property-decorator 的基于类的组件中

Vue关闭组件返回避免直接改变道具

Vue 计算属性改变存储状态