Vue.js: данные не реагируют и не корректно обновляются в методе - PullRequest
0 голосов
/ 07 июля 2019

У меня есть пользовательский компонент, который получает список фильтров для отображения только врачей, выбранных пользователем:

<DoctorsSidebarFilter @update-view='showFilteredDoctors'></DoctorsSidebarFilter>

Далее, в моем основном компоненте я использую это для отображения докторов:

<v-flex
   v-for="doctor in allDoctors"
   :key="doctor.first_name"
   xs12
   sm6
   md4
>

А вот мои данные:

export default {
data: () => ({
        allDoctors:[],
    }),
    methods: {
        fetchDoctors(){
            //Retrieve doctors
            this.$store.dispatch(RETRIEVE_DOCTORS)
            .then(
                response => {
                    this.allDoctors = response;
                }
            )//TODO-me: Handle the error properly!
            .catch(error => {
                console.log(error);
            });
        },
        showFilteredDoctors(filters){
            let result = [];
            this.fetchDoctors();

            console.log('1:' + " " + JSON.stringify(this.allDoctors));
            if (filters.length > 0) { // If Array is not empty then apply the filters
                console.log('2');
                this.allDoctors.forEach(function(e) {
                    if(filters.some(s => s.specialty === e.specialty || s.city === e.city)) {
                        result.push(e);
                    }
                });
                console.log('3:' + " " + JSON.stringify(result));
                this.allDoctors = [...result];
                console.log('4:' + " " + JSON.stringify(this.allDoctors));
            }
        }
    },
    mounted() {
        this.fetchDoctors();
    }
}

Проблема в том, что хотя моя фильтрация работает правильно, и из console.log('4:' + " " + JSON.stringify(this.allDoctors)); я вижу, что this.allDoctors содержит новый отфильтрованный список; это никогда не отображается на экране.

Вместо этого я вижу список врачей по умолчанию, который я получил из своего API. Используя vue devtools, я вижу, что this.allDoctors на мгновенно обновляется с правильными значениями, но затем возвращается к значениям по умолчанию.

Ответы [ 2 ]

3 голосов
/ 07 июля 2019

Как уже объяснил @ user1521685 , вызов fetchDoctors является асинхронным, поэтому он завершится после того, как вы выполните фильтрацию.

Обычно вы делаете что-то подобное, используя вместо этого вычисляемое свойство, и вызываете сервер только один раз.

export default {
    data: () => ({
        allDoctors: [],
        filters: []
    }),
    computed: {
        filteredDoctors() {
            const allDoctors = this.allDoctors;
            const filters = this.filters;

            if (filters.length === 0) {
                return allDoctors;
            }

            return allDoctors.filter(doctor => {
               return filters.some(filter => filter.specialty === doctor.specialty || filter.city === doctor.city);
            });
        }
    },
    methods: {
        fetchDoctors(){
            //Retrieve doctors
            this.$store.dispatch(RETRIEVE_DOCTORS)
            .then(
                response => {
                    this.allDoctors = response;
                }
            )//TODO-me: Handle the error properly!
            .catch(error => {
                console.log(error);
            });
        },
        showFilteredDoctors(filters){
            this.filters = filters;
        }
    },
    mounted() {
        this.fetchDoctors();
    }
}

В вашем шаблоне вы должны использовать:

v-for="doctor in filteredDoctors"
2 голосов
/ 07 июля 2019

fetchDoctors является асинхронным, поэтому в showFilteredDoctors вы выбираете врачей, затем устанавливаете отфильтрованный массив, а затем включается значение fetchDoctors и снова переопределяет врачей: this.allDoctors = response.Вам нужно будет вернуть Обещание в fetchDoctors и использовать его в showFilteredDoctors, например, так: this.fetchDoctors().then(() => /* do the filtering */)

РЕДАКТИРОВАТЬ: вернуть Обещание следующим образом: return this.$store.dispatch(RETRIEVE_DOCTORS).then().catch()

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