Vue JS计算出的属性未重新计算

时间:2019-06-10 19:06:40

标签: javascript laravel vue.js vuejs2 vuetify.js

我有一个 Laravel / Vue JS 应用程序,该应用程序集成了google map组件以及 Vuetify数据表组件。 Vue实例还具有计算属性,该属性根据 Vuetify数据表计算出的另一个计算属性,计算Google Map的点。

视图刀片中的Vue组件代码:

    <v-data-table :ref="model + 'Table'" v-model="selected" :headers="headers" :items="collection" :pagination.sync="pagination" select-all item-key="id" class="elevation-1" >         
    </v-data-table>

    <google-map v-if="mapPoints.length" class="google-map" :markers="mapPoints"></google-map>

Vue实例代码:

var app = new Vue({
el: '#app',
mixins: [ crudFunctionsMixin, adminLayoutMixin ],
data: () => ({
}),
computed: {
    mapPoints: function() {
        return this.calcPoints(this.$refs.prospectTable.filteredItems);
    }
},
methods: {
    calcPoints(items) {
        let myPts = [];
        let i = 0;

        items.forEach(function(prospect) {
            if(prospect.latitude && prospect.longitude) {
                myPts.push({
                    id:     prospect.id,
                    position: {
                        lat: prospect.latitude,
                        lng: prospect.longitude
                    },
                    index: i++,
                    title:  prospect.address + ", " + prospect.city + ", " + prospect.zip,
                    icon:   "\/img\/numberedMapIcons\/number_" + prospect.id + ".png"
                });
            }
        });

        return myPts;
    }
}
});

这不起作用。它将引发类型错误:

  

TypeError:无法读取未定义的属性'filteredItems'

这是因为在GoogleMap组件进行评估时, Vuetify数据表组件中的 filteredItems 计算属性尚未计算。

如果我注释掉使用“ points”计算属性的GoogleMap组件,并在页面渲染后使用 Vue JS Devtools 评估points属性,则这些points属性数据计算正确。这是因为在您使用Devtools访问该计算属性之前,不会第一次评估该计算属性,因此该页面已经呈现。因此,“点数”计算属性在页面呈现后的评估结果很好,但当时GoogleMap组件尝试首先对其进行计算。


接下来,如果“ $ refs.prospectTable.filteredItems” 仍未定义,我尝试修改“点”计算属性以返回空数组。

computed: {
    mapPoints: function() {
        if(!this.$refs.prospectTable)
            return [];
        else
            return this.calcPoints(this.$refs.prospectTable.filteredItems);
    }
}

但是,使用此方法时,在定义 $ refs.prospectTable.filteredItems 之前,已计算的属性仅计算一次,因此它返回空数组。即使更改 $ refs.prospectTable.filteredItems 之后,也不会再对计算所得的属性求值。


为什么每次“ $ refs.prospectTable.filteredItems”更改都不会像从未返回初始空数组时一样重新计算“ mapPoints”计算属性?

computed: {
    mapPoints: function() {
        return this.calcPoints(this.$refs.prospectTable.filteredItems);
    }
}

更新:

根据@larizzatg的建议,将 mapPoints 从计算的属性更改为 mount(())内的$ watch变量可以达到目的:

mounted() {
    this.$watch(
        () => {
            return this.$refs.prospectTable.filteredItems;
        },
        (items) => {
            this.mapPoints = this.calcPoints(items);
        }
    );
}

1 个答案:

答案 0 :(得分:1)

创建vue应用后,将执行计算出的属性。在这一点上,该应用程序在真实的dom中没有组件(ref关键字的功能类似于getElementById,因为未定义prostectTable会导致您未定义)

在已安装的生命周期中,组件位于dom中,因此您可以访问参考。代替计算属性,将观察者添加到refspectTable