多维数组、Vuex 和突变

Posted

技术标签:

【中文标题】多维数组、Vuex 和突变【英文标题】:Multidimensional Arrays, Vuex & Mutations 【发布时间】: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)
  

【问题讨论】:

【参考方案1】:

首先要了解的是,vuex 或任何其他基于flux 架构的状态管理库并非旨在处理嵌套对象图,更不用说您提到的任意/无限嵌套对象了。更糟糕的是,即使是浅状态对象,vuex 在 define 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 很高兴它有帮助。 :)

以上是关于多维数组、Vuex 和突变的主要内容,如果未能解决你的问题,请参考以下文章

第34课 多维数组和多维指针

php计算多维数组某个值的和

JS----使用归递获取多维数组中的某列值

多维数组

PHP中多维数组的问题

如何使用 .slice'd 数组修复 vuex 突变警告