gpt4 book ai didi

javascript - Vue 和 Vuex : Handling dependent computed properties

转载 作者:搜寻专家 更新时间:2023-10-30 22:42:57 25 4
gpt4 key购买 nike

我的应用程序是一个用 Vuex 和 Vuex 构建的精简电子表格。关键组件是 TableCollectionTableRowTableCollection 有一个包含多个 Table 对象的数组。每个 Table 都有一个包含多个 Row 对象的数组。

Row 组件有一个名为 calculatedField 的属性。这只是将行中的两个字段组合起来生成第三个字段。我的选择是将 calculatedField 实现为 Row 组件的本地计算属性,或者作为 Vuex 存储中的 getter。

Table 组件需要一个subTotal 值,该值是通过为表中的所有行添加calculatedField 来计算的。如您所见,subTotal 计算依赖于 calculatedField 计算。

如果我将 calculatedField 实现为 Row 的本地计算属性,它会被缓存。但是,问题是我似乎无法从 Table 父级访问计算字段。我在 Table 中尝试了以下内容:

computed : {
subTotal : function () {
let total = 0;
this.table.rows.forEach(function (row) {
total += row.calculatedField;
});
return total;
}
}

结果是 NaN。

一种解决方案是在 Table 的计算属性中复制 calculatedField 的逻辑,但这不是 DRY。

另一种选择是将 subTotalcalculatedField 都实现为存储中的 getter,但这意味着将参数传递给 gettter (tableIdrowId 或两者),因此不会缓存结果。这看起来效率很低。

最后的可能性是我在全局帮助程序或混合中实现我的 calculatedField 逻辑。这将避免代码重复和 getter 效率低下,但感觉不太对 - 代码专门与 TableRow 相关,理想情况下应保留在那里。

是否还有其他我忽略的解决方案?什么是理想的“Vue-way”?

最佳答案

如果性能是一个问题并且缓存现在很重要,您可能希望Table 组件上实现缓存

Row 组件中,发出新值以便父组件可以缓存它。

  computed: {
calculatedField() {
const result = this.data.field + this.data.other;
this.$emit('change', this.data.id, result);
return result;
}
},

Table 组件中,处理事件并缓存新值。

  data() {
return { cache: {} };
},
computed: {
subTotal() {
return Object.values(this.cache).reduce((total, value) => total + value, 0);
}
},
methods: {
onChange(rowId, val) {
// important for reactivity
this.$set(this.cache, rowId, val);
}
},

Row 的数据更新时,它会触发一个带有新计算值的更改事件,父 Table 使用此缓存跟踪计算值获取小计。

您可以在以下示例中看到计算属性被点击一次,然后在行更改时(单击 Rand 按钮),仅刷新相关的计算属性。

const MyRow = {
props: {
data: {
type: Object
}
},
computed: {
calculatedField() {
console.log("row computed for", this.data.id);
const result = this.data.field + this.data.other;
this.$emit('change', this.data.id, result);
return result;
}
},
methods: {
onClick() {
this.data.other = Math.floor(Math.random() * 10);
}
},
template: `
<tr>
<td>{{ data.field }}</td>
<td>{{ data.other }}</td>
<td>{{ calculatedField }}</td>
<td><button type="button" @click="onClick">Rand</button></td>
</tr>
`
};

const MyTable = {
props: {
rows: {
type: Array
}
},
components: {
MyRow
},
data() {
return {
cache: {}
}
},
computed: {
subTotal() {
console.log("Table subTotal");
return Object.values(this.cache).reduce((total, value) => total + value, 0);
}
},
methods: {
onChange(rowId, val) {
console.log("onChange", rowId, val);
this.$set(this.cache, rowId, val);
}
},
template: `
<div>
<table border="1">
<tr><th>field</th><th>other</th><th>calculated</th><th></th></tr>
<my-row v-for="row in rows" @change="onChange" :key="row.id" :data="row"></my-row>
</table>
Subtotal: {{ subTotal }}
</div>
`
};

var app = new Vue({
el: '#app',
components: {
MyTable
},
data: {
rows: [{
id: 1,
field: 1,
other: 1
},
{
id: 2,
field: 2,
other: 2
},
{
id: 3,
field: 3,
other: 3
},
]
},
template: `<my-table :rows="rows"></my-table>`
});
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

关于javascript - Vue 和 Vuex : Handling dependent computed properties,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49742950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com