Vue.js обновляет массив, не перезагружая все данные - PullRequest
0 голосов
/ 02 ноября 2018

Я новичок в Vue.js и JavaScript. Я просто хочу знать, как обновить массив (при добавлении / редактировании / удалении) и не перезагружать снова все данные. Загружать все данные только при открытии страницы с адресами.

Это мой код:

<template v-else>
<div>
    <div class="page-header with-actions">
        <h1>Addresses</h1>
        <div class="actions">
            <b-btn @click="addAddress" variant="primary"><i class="oi oi-plus"></i> Add Address</b-btn>
        </div>
    </div>
    <div v-if="isLoaded === true">
        <div v-if="addressList.length">
            <b-form @submit.prevent="submit">
                <validation-summary :errors="errors"></validation-summary>

                <div class="row">
                    <div class="col-sm-4" v-for="address in addressList">
                        <div class="card bg-light mb-4">
                            <div class="card-header">
                                {{address.countryName}}
                                <div class="float-right">
                                    <b-btn @click="editAddress(address.id)" class="btn btn-default btn-sm" data-toggle="tooltip" title="Edit address">
                                        <i class="fa fa-edit" aria-hidden="true"></i>
                                    </b-btn>
                                    <b-btn @click="deleteAddress(address.id)" class="btn btn-default btn-sm" data-toggle="tooltip" title="Delete address">
                                        <i class="fa fa-trash" aria-hidden="true"></i>
                                    </b-btn>
                                </div>
                            </div>
                            <div class="card-body">
                                <em class="card-text">{{address.city}},</em><br />
                                <em class="card-text">{{address.streetAddress}},</em><br />
                                <em class="card-text">{{address.zip}}</em><br />
                            </div>
                        </div>
                    </div>
                </div>
            </b-form>
        </div>
        <div v-else class="alert alert-info" role="alert">
            There are no <strong>addresses</strong> yet!
        </div>
    </div>
    <add-address-modal ref="addAddressModal" @success="addressAdded"></add-address-modal>
    <edit-address-modal ref="editAddressModal" @success="addressEdited></edit-address-modal>
</div>
</template>

<script>
import Vue from 'vue';
import modalFormMixin from 'mixins/modal-form-mixin';
import formMixin from 'mixins/form-mixin';
import accountService from 'services/account-service';

import AddAddressModal from './add-address-modal';
import EditAddressModal from './edit-address-modal';

export default {
    mixins: [modalFormMixin],
    mixins: [formMixin],

    components: {
        'add-address-modal': AddAddressModal,
        'edit-address-modal': EditAddressModal
    },

    data() {
        return {
            addressList: [],
            isLoaded: false,
        }
    },

    async beforeRouteEnter(to, from, next) {
        next(async (c) => await c.initData());
    },

    methods: {
        async initData() {
            await this.loadAddressList(); //when opening page

            this.isLoaded = true;
        },

        async loadAddressList() {
            this.addressList = await accountService.getAddressList();
        },

        addAddress(data) {
            this.$refs.addAddressModal.show();
        },

        editAddress(id) {
            this.$refs.editAddressModal.show(id);
        },

        async deleteAddress(id) {
            await accountService.deleteAddress(id);

            this.loadAddressList(); //need to change

            this.$root.successToast('Address deleted');
        },

        addressAdded() {
            this.loadAddressList(); //need to change

            this.$root.successToast('Address added');
        },

        addressEdited() {
            this.loadAddressList(); //need to change

            this.$root.successToast('Address edited');
        }
    }
}
</script>

Так что мне нужно изменить loadAddressList (), потому что он снова загружает все данные адресов после добавления / редактирования / обнаружения. Что будет лучшим решением для этого?

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Интересно, не могли бы вы использовать then? Так, например, в вашем initiData методе вы можете сделать это?

async initData() {
    this.loadAddressList()
        .then(() => {
             this.isLoaded = true;
        });
    },

Это означает, что вам не нужно обновлять метод loadAddressList и заставлять его ждать или выполнять другие функции, за которые он действительно не должен нести ответственность?

ОБНОВЛЕНИЕ: Вы также должны убедиться, что ваш метод loadAddressList возвращает некоторое значение, поскольку он использует ключевое слово async, возвращающее обещание.

async loadAddressList() {
    this.addressList = await accountService.getAddressList();
    return true
},

Тогда .then() будет работать в вашем initData() методе.

Также см. Снимок экрана с https://javascript.info/async-await

enter image description here

0 голосов
/ 02 ноября 2018

С vue 2.0 лучше всего убедиться, что изменение данных вызывает обновление dom каждый раз, это Vue.set с ассоциативными массивами (объектами объектов), но для большей эффективности ваш запрос на обновление / создание должен вернуть объект, тогда вы можете либо вставьте его в массив или используйте этот метод:

import Vue from 'vue'
createAddress(data) {
   axios.POST('your-url', data).then( address => {
       Vue.set($store.addresses, address.id, address)
   })
}

Чтобы использовать это, вы должны изменить свой массив адресов для такой ассоциации:

import Vue from 'vue'

getAddresses(state) {
   axios.GET('your-url').then(addresses => {
       addresses.forEach(address => {
            Vue.set(state.addresses, address.id, address)
       })
   })
}

Вы также можете сделать это с

Object.assign(state.addresses[address.id], address)

но по моему опыту это иногда не обновляет dom по неизвестной причине.

тогда ваш address_list должен быть вычисленным, который указывает на адреса в вашем управлении состоянием (vuex или другое)

computed: {
    address_list() {
        return $store.addresses
    }
}
0 голосов
/ 02 ноября 2018

Я уже не справился с этой проблемой. Это связано с Реактивностью и тем, как изменения могут быть отложены на тик.

Пример решения вашей проблемы.

methods: {
  async loadAddressList() {
    this.addressList = await accountService.getAddressList();
    await this.$nextTick() // waits for the next event tick before completeing function.
  },
}

Загляните в Очередь асинхронных обновлений .

Кроме того, обратите внимание на Обнаружение изменений массива Замена массива выполняет эффективную работу по повторному использованию элементов DOM.

Удачи.

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