如何管理 Vuex Store 中的嵌套数组并通过组件传递

Posted

技术标签:

【中文标题】如何管理 Vuex Store 中的嵌套数组并通过组件传递【英文标题】:How to manage nested arrays in Vuex Store and pass it trough component 【发布时间】:2018-03-21 19:37:44 【问题描述】:

在我的 Vuex Store 中,我有一个计划状态,它描述了一周的计划。

planning : [
        
            name : 'monday',
            meetings : [
                
                    name : 'morning',
                    value : ''
                , 
                    name : 'noon',
                    value : ''
                , 
                    name : 'evening',
                    value : ''
                ]
        ,
        
            name : 'tuesday',
            meetings : [
                
                    name : 'morning',
                    value : ''
                , 
                    name : 'noon',
                    value : ''
                , 
                    name : 'evening',
                    value : ''
                ]
        ,

        ...

    
]

为了显示我拥有的所有东西

PlanningWeek.vue

<template>
    <div class="week columns is-desktop is-vcentered">
        <PlanningDay v-for="(day, index) in planning" :key="index" :day="day"></PlanningDay>
    </div>
</template>

<script>
    import PlanningDay from './PlanningDay';
    import  mapState  from 'vuex';

    export default 
        computed : mapState(['planning']),
        components : 
            PlanningDay
        ,
    ;
</script>

我每天都有 PlanningDay.vue,它从他的道具中检索当天,然后渲染它,但它是 Vuex 的一种方式。因为通常我们总是必须从 Vuex 商店获取/设置(提交)。

在 Vuex Store 中渲染嵌套数组的最佳方式是什么?

我继续使用嵌套代码,以便您可以看到所有内容

PlanningDay.vue

<template>
    <div class="day column">
        <p class="name has-text-centered" v-text="day.name"></p>

        <PlanningMeeting v-for="(meeting, index) in day.meetings" :key="index" :meeting="meeting"></PlanningMeeting>
    </div>
</template>

<script>
    import PlanningMeeting from './PlanningMeeting';

    export default 
        props : ['day'],
        components : 
            PlanningMeeting
        
    ;
</script>

最后是 PlanningMeeting.vue

<template>
    <div class="meeting">
        <p class="has-text-centered" v-text="meeting.name"></p>
        <input type="text" v-model="meeting.value">      
    </div>
</template>

我怎样才能绑定来自 PlanningDay 的道具来自 PlanningWeek 的 meeting.value?

由于通过提交进行修改以更改状态,因此看起来像这样:

<script>
    export default 
        props : ['meeting'],
        computed : 
            meetingList : 
                get() 
                    return this.$store.state.planning[planningId].meetings[meetingId];
                ,
                set(value) 
                    this.$store.commit('updateValue', ...planningId, meetingId, ... value);
                
            
        ,
    ;
</script>

所以我会将 v-model 与 meetingList 计算属性或类似的东西绑定,但是如何设法检索 PlanningId 和 meetingId,我的意思是以正确的方式。由于 Vuex 的重点是不要把事件和道具放在任何地方并提取这个数据层。

所以我做错了什么?以及如何在 Vuex 中管理嵌套数组以将数据传递给嵌套组件的最佳方法是什么?

提前感谢您的回答!

【问题讨论】:

【参考方案1】:

如果我没记错的话,您是在尝试将输入中的值保存到 vuex 状态,即 meeting.value 对象。

首先,您需要将输入绑定到单独的对象中。这种方式:

data () 
  return 
    value: null
  

然后在你的模板部分,

<input type="text" v-model="value">
<button @click="onValueSaved"></button>

你需要声明一个方法来将值保存到 vuex 状态,

methods: 
   onValueSaved () 
     this.$store.commit('SET_MEETING_VALUE', this.value)
   

【讨论】:

【参考方案2】:

最好的办法是避免嵌套结构。这也是其他全局状态单状态树系统(如 redux)中的既定模式。但这里不需要 Redux。对数据进行规范化是个好主意,是的 - redux 中用于这些东西的模式也适用于 vuex。

归一化基本上意味着你转动这个:

planning : [
    
        name : 'monday',
        meetings : [
            
                name : 'morning',
                value : ''
            , 
                name : 'noon',
                value : ''
            , 
                name : 'evening',
                value : ''
            ]
    ,
    
        name : 'tuesday',
        meetings : [
            
                name : 'morning',
                value : ''
            , 
                name : 'noon',
                value : ''
            , 
                name : 'evening',
                value : ''
            ]
    ,

    ...


]

进入这个:

planning: 
  name: [monday,tuesday],
  meetings: 
    monday:  id: 'monday', name: [1,2,3] ,
    tuesday:  id: 'tuesday', name: [4,5,6] ,
  
,
name : 
   meetings : 
    1: id: 1, text: 'morning' , value: '',
    2: id: 2, text: 'noon' , value: '',
    3: id: 3, text: 'evening' , value: '',        
    4: id: 4, text: 'morning' , value: '',
    5: id: 5, text: 'noon' , value: '',
    5: id: 6, text: 'evening' , value: '',        
    

现在你可以在 Vuex Store 中实现简单的 getter 和 setter。看起来它更复杂了,在某种程度上它有点复杂。但好处是,对于更新,您在编写突变时不必担心任何与嵌套相关的问题。

例如:如果您需要所有计划的排序数组,则编写一个 getter:

planningArray (state) => 
  return state.planning.list.map  
            name => state.planning.meetings[name]
  

使用这个你不需要传递道具。对于每次更改,您将数据推送到 Store 并使用“计算/方法”将其检索到另一个组件中

【讨论】:

以上是关于如何管理 Vuex Store 中的嵌套数组并通过组件传递的主要内容,如果未能解决你的问题,请参考以下文章

vuex总结

什么是vuex?他有什么作用?如何改变store中的状态(state)?

vue中如何监听vuex中的数据变化

vuex进一步使用

Vue 中 store 基本用法

vuex 中操作数组,报错 Do not mutate vuex store state outside mutation handlers