【问题标题】:Multidimensional Arrays, Vuex & Mutations多维数组、Vuex 和突变
【发布时间】:2019-03-15 18:39:13
【问题描述】:

我正在尝试在 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 商店内?

我通常使用 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)
  }
}

【问题讨论】:

    标签: arrays recursion multidimensional-array vuex mutation


    【解决方案1】:

    首先要了解的是,vuex 或任何其他基于flux 架构的状态管理库并非旨在处理嵌套对象图,更不用说您提到的任意/无限嵌套对象了。更糟糕的是,即使是浅状态对象,vuexdefine the shape of the state (all desired fields) upfront 时效果最好。

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

    1。规范化您的数据

    这是 vue.js 团队成员 [here][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中提到的第二种方法:

    向对象添加新属性时,您应该:

    • 使用Vue.set(obj, 'newProp', 123),或

    • 用一个新的对象替换那个对象

    ...

    您可以使用另一个库轻松实现此目的: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 所做的更改。如果您不想对数据进行规范化/非规范化,这种方法是可取的。

    【讨论】:

    • 非常感谢您的回答,这正是我所需要的。
    • @muffinlab 很高兴它有帮助。 :)
    猜你喜欢
    • 2017-11-23
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2020-12-17
    • 2017-10-13
    • 2018-09-12
    • 1970-01-01
    • 2018-02-04
    相关资源
    最近更新 更多