Значение данных не обновляется с помощью вкладок в Vue JS - PullRequest
0 голосов
/ 24 октября 2018

Привет, ребята. Я пытаюсь создать свои собственные вкладки, с Vue js, но у меня возникла проблема, поскольку, как и у меня, свойство данных не обновляется: (... Вот случай, с которым у меня возникают проблемы: Когда я открываю 3 вкладки,Если я открою свой модальный режим на первой вкладке, а затем закрою эту первую вкладку, я переключусь на вторую вкладку, но мой модальный, который был с первой вкладки, останется открытым, как будто он модальный с первой вкладки, а не второй ... Я хотел быкаждая вкладка имеет свой собственный модальный экземпляр.

Здесь я разместил ниже GIF о том, что происходит. По сути, я не хочу, чтобы мой модал снова появлялся на следующей вкладке, когда предыдущая закрыта:)

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>

Мой компонент Tab:

<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>

Мой модальный компонент для отображения Dialog:

<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

Спасибо заранее.

1 Ответ

0 голосов
/ 25 октября 2018

Решил это.Проблема с ключами в v-for: key prop, должна быть уникальной, вот как я это решил, в мутациях addNew добавьте новое свойство tabId add, например:

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

и App.vue change: key = «index» на: key = «event.tabId»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...