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

时间:2017-10-10 11:48:51

标签: arrays vue.js nested store vuex

在我的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 : ''
                }]
        },

        ...

    }
]

显示我有类似内容的所有内容

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的道具的meeting.value来自PlanningWeek?

由于修改是通过提交来改变状态,因此看起来像这样:

<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中管理嵌套数组以将数据传递给嵌套组件的最佳方法是什么?

先谢谢你回答!

2 个答案:

答案 0 :(得分:2)

最好的办法是避免嵌套结构。这是其他全局状态单状态树系统(如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中,并使用“computed / methods”

将其检索到另一个组件中

答案 1 :(得分:0)

如果我没弄错,你试图将输入值保存到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)
   }
}