Vue JS计算属性没有重新计算
Posted
技术标签:
【中文标题】Vue JS计算属性没有重新计算【英文标题】:Vue JS computed property not recalculating 【发布时间】:2019-10-25 04:41:15 【问题描述】:我有一个 Laravel / Vue JS 应用程序,它集成了一个谷歌地图组件以及一个 Vuetify 数据表 组件。 Vue 实例还有一个计算属性,用于计算 Google 地图的点,该属性基于 Vuetify 数据表 计算的另一个计算属性。
视图刀片中的 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”
这是因为 Vuetify 数据表 组件中的 filteredItems 计算属性在 GoogleMap 组件评估它时尚未计算。
如果我注释掉使用 "points" 计算属性的 GoogleMap 组件,并在页面渲染后使用 Vue JS Devtools 评估 points 属性,则 points 属性数据计算正确。这是因为计算属性在您使用 Devtools 访问它之前不会第一次评估,因此页面已经呈现。因此,“points”计算属性在页面渲染后评估良好,但此时 GoogleMap 组件尝试首先计算它。
如果 "$refs.prospectTable.filteredItems" 仍未定义,我接下来尝试修改 "points" 计算属性以返回一个空数组。
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 从计算属性更改为 mounted() 内的 $watch 变量就成功了:
mounted()
this.$watch(
() =>
return this.$refs.prospectTable.filteredItems;
,
(items) =>
this.mapPoints = this.calcPoints(items);
);
【问题讨论】:
【参考方案1】:创建 vue 应用程序时,会执行计算的属性。此时,应用程序在真实 dom 中没有该组件(ref 关键字的功能类似于 getElementById,因为 prostectTable 未定义,所以您未定义)
在挂载的生命周期中,组件位于 dom 中,因此您可以访问 ref。将观察者添加到 refs 前景表中,而不是计算属性
【讨论】:
在 "$refs.prospectTable.filteredItems" 上添加监视有效,但仅在 mount() 中设置 $watch 时有效。谢谢!以上是关于Vue JS计算属性没有重新计算的主要内容,如果未能解决你的问题,请参考以下文章
[Vue] 计算属性Computed与函数function的异同
使用带有 Avoriaz 的 AVA 在 Vue.js 中测试计算属性