Javascript 使用Vuex,当项目是对象数组的一部分时,如何从数组中删除它们?

Javascript 使用Vuex,当项目是对象数组的一部分时,如何从数组中删除它们?,javascript,vue.js,vuejs2,vuex,Javascript,Vue.js,Vuejs2,Vuex,此处引用实时演示代码: 假设我有一个Vuex存储,其中包含以下数据: const store = new Vuex.Store({ state: { categories: [ { name: "Category A", items: [{ name: "Item 1" }, { name: "Item 2" }, { name: "Item 3" }] }, { name: "Category B

此处引用实时演示代码:

假设我有一个Vuex存储,其中包含以下数据:

const store = new Vuex.Store({
  state: {
    categories: [
      {
        name: "Category A",
        items: [{ name: "Item 1" }, { name: "Item 2" }, { name: "Item 3" }]
      },
      {
        name: "Category B",
        items: [{ name: "Item A" }, { name: "Item B" }, { name: "Item C" }]
      },
      {
        name: "Category C",
        items: [{ name: "Item !" }, { name: "Item @" }, { name: "Item #" }]
      }
    ]
  }
});
我有一个
App.vue
Category.vue
Item.vue
,它们被设置为如下所示:

//App.vue
<template>
  <div id="app">
    <Category v-for="(category, index) in categories" :category="category" :key="index"/>
  </div>
</template>

<script>
  export default {
    components: { Category },

    computed: {
      ...mapState(["categories"])
    }
  };
</script>
//App.vue
导出默认值{
组件:{Category},
计算:{
…映射状态([“类别”])
}
};
//Category.vue
{{category.name}
导出默认值{
组件:{Item},
道具:{
类别:{type:Object,必需:true}
}
};
//Item.vue
{{item.name}
✖
导出默认值{
道具:{
项:{type:Object,必需:true}
},
方法:{
onDelete(){
此.store.commit(“deleteItem”,this.item);
}
}
};
换句话说,
App.vue
从Vuex获取类别列表,然后将其作为每个类别的道具传递给
Category.vue
,然后
Category.vue
Category.items
传递给
Item.vue
作为每个项目的道具

单击项目旁边的“删除”按钮时,我需要删除该项目:

但是,在
Item.vue
级别,我只能访问
,而不能访问
类别
。如果我将
项目
发送到Vuex,我无法判断它属于哪个
类别
。如何获取对
类别的引用
,以便使用Vuex从中删除该项目

我可以想出两种方法:

  • 为每个
    项目
    将父级引用添加回
    类别
    。这是不受欢迎的,不仅因为我必须处理
    数据,还因为它引入了一个循环引用,我不想在应用程序的其他部分处理它

  • Item.vue
    Category.vue
    发出事件,并让
    Category.vue
    处理要删除的Vuex调用。这样,类别和要删除的项目都是已知的

  • 有没有更好的方法来处理这种删除?

    我强烈推荐(2)。通常,如果您可以创建一个组件,该组件使用道具并发出事件,而不会产生其他副作用(API调用、Vuex突变等),那么这通常是正确的路径。在这种情况下,您甚至可以将事件一直推回到父级的父级

    共享状态(Vuex)真正有用的地方是当DOM树中有两个或多个彼此相距较远的组件时。例如,想象一个标题中有一个项目总数。这种程度的空间分离可能存在于你的应用程序中,但在这个简单的例子中并不存在

    在这里发出事件的另一个好处是,您可以更轻松地使用诸如无需处理任何Vuex解决方案之类的工具。

    就个人而言,我选择2(从
    Item.vue
    Category.vue
    )发出事件),但是,由于您询问了可能性,还有第三种方法:传递回调函数

    例如:

    Category.vue

    <template>
      <div class="category">
        <div class="header">{{ category.name }}</div>
        <Item v-for="(item, index) in category.items" :item="item" :key="index"
         :on-delete="deleteItem"/>
      </div>
    </template>
    
    <script>
    // ...
    export default {
      // ...
      methods: {
        deleteItem(i) {
          console.log('cat', this.category.name, 'item', i)
          //this.$store.commit("deleteItem", this.item);
        }
      }
    };
    </script>
    
    <template>
      <div class="item">
        <div class="name">{{ item.name }}</div>
        <div class="delete" @click="() => onDelete(this.item)">&#10006;</div>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        item: { type: Object, required: true },
        onDelete: { type: Function }
      },
    };
    </script>
    
    。注意,在本例中,回调是
    onDelete


    如果这是React,那么回调肯定是一种更惯用的方式。如前所述,在Vue中,我赞成在子系统中发出事件,并在父系统中处理它(使用
    v-on
    )。

    当然,您也可以在
    类别中声明。Vue
    :on delete=“deleteItem(item)”
    ,这使得它更接近事件选项。
    <template>
      <div class="category">
        <div class="header">{{ category.name }}</div>
        <Item v-for="(item, index) in category.items" :item="item" :key="index"
         :on-delete="deleteItem"/>
      </div>
    </template>
    
    <script>
    // ...
    export default {
      // ...
      methods: {
        deleteItem(i) {
          console.log('cat', this.category.name, 'item', i)
          //this.$store.commit("deleteItem", this.item);
        }
      }
    };
    </script>
    
    <template>
      <div class="item">
        <div class="name">{{ item.name }}</div>
        <div class="delete" @click="() => onDelete(this.item)">&#10006;</div>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        item: { type: Object, required: true },
        onDelete: { type: Function }
      },
    };
    </script>