代码之家  ›  专栏  ›  技术社区  ›  kingJulian

Vue。js:数据不是反应性的,在方法中没有正确更新

  •  0
  • kingJulian  · 技术社区  · 6 年前

    我有一个自定义组件,它接收过滤器列表,以便仅显示用户选择的医生:

    <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,我可以看到 这所有医生 瞬间 使用正确的值进行更新,但随后会返回默认值。

    0 回复  |  直到 6 年前
        1
  •  3
  •   skirtle    6 年前

    @用户1521685 已经解释过了,打电话给 fetchDoctors 是异步的,因此它将在您执行过滤后完成。

    通常,您会使用computed属性执行类似的操作,并且只进行一次服务器调用。

    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
  •  2
  •   user1521685    6 年前

    fetchDoctors 是异步的,所以在 showFilteredDoctors 你去叫医生,然后设置过滤后的数组,然后再输入thenable 请医生 再次介入并超越医生: this.allDoctors = response . 你得把承诺及时还给我 请医生 并将其用于 ShowFilterEdotors 就像这样: this.fetchDoctors().then(() => /* do the filtering */)

    编辑:像这样返回承诺: return this.$store.dispatch(RETRIEVE_DOCTORS).then().catch()