多维数组、Vuex 和突变

Multidimensional Arrays, Vuex & Mutations

我正在尝试在 Vuex 中存储的多维数组中添加和删除项目。

数组是一组类别,每个类别又有一个子类别(无穷大,不是简单的二维数组)。

示例数据集是这样的:

[
   {
     id: 123,
     name: 'technology',
     parent_id: null,
     children: [
          id: 456,
          name: 'languages',
          parent_id: 123,
          children: [
             {
                id:789,
                name: 'javascript',
                parent_id: 456
             }, {
                id:987,
                name: 'php',
                parent_id: 456
             }
          ]
        }, {
          id: 333,
          name: 'frameworks', 
          parent_id 123,
          children: [
             {
                id:777,
                name: 'quasar',
                parent_id: 333
             }
          ]
        }
     ]
   }
]

.....我的问题是,如何最好地向 Vuex Store 内部的数组添加和删除元素?

我通常使用 Vue.Set() 来操作 Vuex Store 中的简单数组以获得反应性。但是,因为我不确定被操作的嵌套数组有多深 - 我根本无法弄清楚。

这是我认为可以使用递归添加子类别元素的示例:

export const append = (state, item) => {
  if (item.parent_uid !== null) {
    var categories = []
    state.data.filter(function f (o) {
      if (o.uid === item.parent_uid) {
        console.log('found it')
        o.push(item)
        return o
      }
      if (o.children) {
        return (o.children = o.children.filter(f)).length
      }
    })
  } else {
    state.data.push(item)
  }
}

首先要了解的是 vuex 或任何其他基于 flux 体系结构的状态管理库并非旨在处理嵌套对象图,更不用说 arbitrary/infinity您提到的嵌套对象。更糟糕的是,即使使用浅状态对象,vuexdefine the shape of the state (all desired fields) upfront.

时效果最好

恕我直言,您可以采取两种可能的方法

1。标准化您的数据

这是 vue.js 团队成员 [此处][2] 推荐的方法。

如果你真的想在规范化后保留有关层次结构的信息,你可以使用 flat 与转换函数结合使用,通过 name 将你的嵌套对象扁平化为这样的东西:

const store = new Vuex.Store({
  ...
  state: {
    data: {
      'technology':                      { id: 123, name: 'technology', parent_id: null },
      'technology.languages':            { id: 456, name: 'languages', parent_id: 123 },
      'technology.languages.javascript': { id: 789, name: 'javascript', parent_id: 456 },
      'technology.languages.php':        { id: 987, name: 'php', parent_id: 456 },
      'technology.frameworks':           { id: 333, name: 'frameworks', parent_id: 123 },
      'technology.frameworks.quasar':    { id: 777, name: 'quasar', parent_id: 333 },
    }
  },
});

然后您可以像往常一样对 state.data 中的每个项目使用 Vue.set()

2。在修改时创建一个全新的状态对象

这是vuex's documentation中提到的第二种方法:

When adding new properties to an Object, you should either:

  • Use Vue.set(obj, 'newProp', 123), or

  • Replace that Object with a fresh one

...

您可以使用另一个库轻松实现此目的:object-path-immutable。例如,假设你想在 languages 下添加新类别,你可以像这样创建一个突变:

const store = new Vuex.Store({
  mutations: {
    addCategory(state, { name, id, parent_id }) {
      state.data = immutable.push(state.data, '0.children.0.children', { id, name, parent_id });
    },
  },
  ...
});

通过在每次进行修改时将 state.data 重新分配给一个新对象,vuex 反应系统将正确地通知您对 state.data 所做的更改。如果您不想 normalize/denormalize 您的数据,这种方法是可取的。