数据值未使用Vue js中的选项卡更新

时间:2018-10-23 21:13:36

标签: javascript vue.js vuex

大家好,我试图用Vue js制作我的自定义标签,但是我遇到了问题,因为像我的data属性没有得到更新:(... 这是我遇到麻烦的情况: 当我打开3个选项卡时,如果我在第一个选项卡上打开我的模态,然后关闭该第一个选项卡,我将切换到第二个选项卡,但是来自第一个选项卡的我的模态保持打开状态,就像它是第一个选项卡而不是第二个模态...我希望每个标签都有自己的模态实例。

在这里,我发布了正在发生的事情的下面的表情。基本上,当上一个页面关闭时,我不希望我的模式再次出现在下一个选项卡上:)

My test case

好像我的数据值一样,不会在第一个选项卡中销毁,而是将它们复制到第二个选项卡上,我试图在几天之内找出问题所在,但没有成功...

这是我的App.vue

<template>
    <div id="app">
        <div class="event-tabs wrapper">
            <div class="is-flex">
                <div class="tabs is-boxed control">
                    <ul>
                        <li v-for="(newEvent, index) in newEventList" :key="index"  :class="selectedEventClass(index)"
                        @click.left="selectEvent(index)" @click.middle="discardEvent(index)">
                             <span class="event-tab-title">
                            TAB
                            </span>
                            <span class="event-tab-close" @click.stop="closeEvent(index)">
                            <i class="fa fa-times"></i>
                         </span>
                        </li>
                        <li class="add-tab">
                            <a @click.prevent="createEvent" :title="'Create Tab'">
                            <span>+</span>
                        </a>
                        </li>
                    </ul>
                </div>
            </div>
                <div class="tab-content">
                    <tab v-for="(event, index) in newEventList" :event="event" :index="index"
                    v-if="showEventTab" v-show="index === selectedEvent" :key="index"
                    ref="eventTab"></tab>
                </div>
        </div>
    </div>
</template>
<script>
    import tab from './components/EventTab.vue';
    export default {
        name: 'app',
        components: {
            tab,
        },
        computed: {
            newEventList() {
                return this.$store.getters['eventModule/getNewList'];
            },
            selectedEvent() {
                return this.$store.getters['eventModule/getSelectedNew'];
            },
            eventToEdit() {
                return this.$store.state.event.eventToEdit;
            },
            showEventTab() {
                return this.newEventList.length > 0;
            },
        },
        methods: {
            selectedEventClass(eventIndex) {
                return (eventIndex === this.selectedEvent) ? 'is-active' : '';
            },
            createEvent() {
                this.$store.dispatch('eventModule/create');
            },
            selectEvent(eventIndex) {
                this.$store.dispatch('eventModule/select', { eventIndex });
            },
            closeEvent(eventIndex) {
                this.$store.dispatch('eventModule/close', { eventIndex });
            },
        },
    }
</script>

<style lang="scss">
    @import './assets/scss/main';
</style>

“我的标签”组件:

<template>
     <div class="event-form" v-if="event">

        <div class="columns">
            <div class="column is-half">
            <div class="field">
                <h1>This is the TAB number {{ index}} </h1>
            </div>
            <p class="control">
                <button class="button is-danger" @click.prevent="openDialog">
                    Open Dialog
                </button>
            </p>
            <modalDialog  type="none" :show="modal.show"
                             :className="'eventTabModal'" :title="'Test modal'"
                             :text="'Test modal'"
                             @hide="closeDiscardModal">
                                <h3>Modal is active</h3>
                             </modalDialog>
         </div>                      
        </div>
     </div>
</template>

<script>
    import modalDialog from './ModalDialog.vue';
    export default {
        components: {
            modalDialog,
        },
        props: ['event', 'index'],
        data() {
            return {
                eventDefault: {},
                /**
                 *  Discard event modal
                 */
                modal: {
                    show: false,
                },
            };
        },
        computed: {
            eventList() {
                return this.$store.getters['event/getNewList'];
            },
            eventTypeList() {
                return this.$store.getters['eventType/getList'];
            },
        },
        methods: {
            /**
             * Opens discarded Modal
             */
            closeDiscardModal() {
                this.modal = {
                    show: false,
                };
            },
            openDialog() {
                this.modal = {
                    show: true,
                };
            },   
        },
    }
</script>

用于显示对话框的我的模态组件:

<template>
    <transition name="fade">
        <div class="modal is-active" v-show="shouldShowModal" :class="className">
            <div class="modal-background" @click="hideModal"></div>
            <div class="modal-card">
                <header class="modal-card-head" v-if="title">
                    <p class="modal-card-title">{{ title }}</p>
                </header>
                <section class="modal-card-body">
                    <slot>
                        {{ text }}
                    </slot>
                </section>
                <footer class="modal-card-foot" v-if="type !== 'none'">
                    <template v-if="type === 'confirm'">
                        <a class="button is-success" @click.prevent="buttonClicked('yes')">Yes</a>
                        <a class="button is-danger" @click.prevent="buttonClicked('no')">No</a>
                    </template>
                    <template v-else-if="type === 'info'">
                        <a class="button" @click.prevent="buttonClicked('ok')">Ok</a>
                    </template>
                </footer>
            </div>
            <button class="modal-close is-large" @click="hideModal"></button>
        </div>
    </transition>
</template>

<script>
    export default {
        props: {
            show: {
                type: Boolean,
                default: false,
            },
            title: {
                type: String,
                default: '',
            },
            text: {
                type: String,
                default: '',
            },
            type: {
                type: String,
                default: 'info',
            },
            className: {
                type: String,
                default: '',
            },
        },
        data() {
            return {
                shouldShowModal: this.show,
            };
        },
        watch: {
            show(newValue) {
                this.shouldShowModal = newValue;
            },
        },
        methods: {
            hideModal() {
                this.shouldShowModal = false;
                this.$emit('hide');
            },
            buttonClicked(type) {
                this.hideModal();
                this.$emit('buttonClicked', type);
            },
        },
    };
</script>

“标签”的“我的商店”模块:

const eventModule = {
    namespaced: true,
    state: {
        /**
         * List of opened tabs
         */
        newList: [],
        selectedNew: 0,
        savedList: [],
        eventToEdit: null,
    },
    getters: {
        getNewList(state) {
            return state.newList;
        },
        getSelectedNew(state) {
            return state.selectedNew;
        },
        getSavedList(state) {
            return state.savedList;
        },
    },
    mutations: {
        addNew(state, { location } = {}) {
            state.newList.push({
                typeId: null,
                active: true,
                logs: [],
            });
        },
        removeNew(state, index) {
            state.newList.splice(index, 1);
        },
        setNew(state, { index = state.selectedNew, event }) {
            state.newList.splice(index, 1, event);
        },
        selectNew(state, selectedNew) {
            state.selectedNew = selectedNew;
        },
    },
    actions: {
        /**
         * opens tab for creating new event
         *
         * @param context
         * @param location
         * @param stopProp
         * @returns {*}
         */
        create(context, { location, stopProp } = {}) {
            const newList = context.getters.getNewList;

            context.commit('addNew', { location });
            context.commit('selectNew', newList.length - 1);

            // if (!stopProp) {
            //     context.dispatch('stateChanged', null, { root: true });
            // }

            return Promise.resolve();
        },
        /**
         * Saves event
         * @param context
         * @param event
         * @return {Promise|Promise.<TResult>}
         */
        save(context, { event, index, hideMessage }) {
            const method = (event.id) ? 'patch' : 'post';
            // const data = { event, userId: context.rootGetters['user/getData'].id };
            const data = { event };
            const payload = { method, url: 'event', data, hideMessage };

            return context.dispatch('server/http', payload, { root: true })
                .then((response) => {
                    context.commit('setNew', { event: response.data.object, index });
                    context.dispatch('loadList');
                })
                .catch(error => Promise.reject(error));
        },
        select(context, { eventIndex, stopProp }) {
            context.commit('selectNew', eventIndex);

        },
        opened(context) {
            const event = JSON.parse(JSON.stringify(context.state.eventToEdit));

            context.state.eventToEdit = null;
            context.dispatch('create', { stopProp: true });
            context.commit('setNew', { event });
        },
        /**
         * Closes for event
         * @param context
         * @param eventIndex
         * @param stopProp
         * @return {Promise|Promise.<TResult>}
         */
        close(context, { eventIndex, stopProp }) {
            const newList = context.getters.getNewList;
            const selectedNew = context.getters.getSelectedNew;

            context.commit('removeNew', eventIndex);

            if (selectedNew >= newList.length && selectedNew > 0) {
                context.commit('selectNew', selectedNew - 1);
            }
        },
    },
};

export default eventModule;

这也是我的github页面的链接,如果有人想看一下,这里有完整的测试代码:

Codesandbox link

先感谢

1 个答案:

答案 0 :(得分:0)

解决了。问题在于v-for中的键,:key prop应该是唯一的,所以这是我解决的方法,在addNew变量中,添加新属性tabId像这样添加:

state.newList.push({
                tabId: new Date.now(),
                typeId: null,
                active: true,
                briefing: false,
                logs: [],
});

和App.vue将:key =“ index”更改为:key =“ event.tabId”