Vue3中transactions_with_balance计算属性未随依赖更新问题
问题描述
Stack Overflow上有许多类似前提的问题,但多为旧问题且基于Vue2解答。由于Vue2与Vue3差异较大,故提出新问题。
我定义了如下两个计算属性:
const transactions_map = computed(()=>{ if (!tenants.value){ return {} } const _val = {}; for (const [key, value] of tenants.value.entries()){ const _transactions = value.transactions; const nm = DataMap.fromArray(_transactions, {sortKey: 'date'}) _val[key] = nm; } return _val }) const transactions_with_balance = computed(() => { const return_value = {} Object.entries(transactions_map.value) .forEach(([key, value])=>{ let prevTotal = 0; const nm = new DataMap() for (const [tran_key, tran_val] of value.entries()){ const _tran = {...tran_val}; _tran.balance = _tran.amount + prevTotal prevTotal = _tran.balance nm.set(tran_key, _tran) } return_value[key] = nm }) return return_value })
当我通过transactions_map['some_tenant_id'].set('some_transaction_id', new_transaction_object)向transactions_map返回的对象中添加值时,transactions_with_balance并未随之更新。根据Vue3文档,其应具备深度响应性。此处的DataMap是一个带有辅助方法的Map类,是否Vue3无法检测到底层Map的变更?
问题原因与解决方案
是的,Vue3无法自动检测到自定义Map类(比如你的DataMap)内部的变更。Vue3的响应式系统对原生Map的set/delete等操作能正常追踪,但对于继承或封装原生Map的自定义类,Vue没法感知到其内部方法触发的状态变化——因为Vue的响应式代理只针对原生对象/集合,自定义类的方法如果没触发依赖更新,计算属性就不会重新执行。
可行的解决办法:
- 改用原生Map:如果业务逻辑允许,直接使用原生
Map替代DataMap,Vue3会自动追踪它的所有操作,此时transactions_with_balance会自动更新。 - 手动触发响应更新:如果必须保留DataMap,在修改DataMap后,手动触发相关响应式依赖的更新。比如若
tenants是ref对象,可以调用triggerRef(tenants):import { triggerRef } from 'vue' // 在调用DataMap.set之后执行 triggerRef(tenants) - 封装DataMap的响应式方法:修改DataMap的
set等核心方法,在内部调用Vue的响应式API通知变更。比如在set方法执行后,触发对应依赖的更新,但这种方式需要修改自定义类的实现。
另外需要注意:transactions_map返回的是普通对象,对象里的属性是DataMap实例。当你修改DataMap内部状态时,这个普通对象的引用并未改变,Vue的响应式系统不会感知到对象属性内部的状态变化——只有当对象属性被重新赋值,或者原生集合的方法被调用时,才会触发更新。
内容的提问来源于stack exchange,提问作者Jamie Marshall
相关产品推荐
相关产品推荐

