Vue3 computed属性onMounted中打印值与对象值不一致如何排查
Vue3 CDN项目computed值打印不一致问题排查
问题背景
- 学习Vue一周,采用CDN方式开发小型Vue3应用,全程使用Composition API实现功能
- 注意:
state.allCvls是通过*axios.get*调用REST接口获取的响应式变量
问题代码如下:
... const allCvlCount = computed (() => { return state.allCvls.length; // 值来自REST接口的axios调用返回 }); ... onMounted (() => { console.log(allCvlCount); console.log(allCvlCount.value); })
- 异常表现:在
onMounted钩子中同时打印computed对象本身和它的value属性时,二者显示的值存在差异,异常截图如下:
- 自行编写测试用例尝试复现问题,测试用例运行正常未复现异常,测试代码如下:
<!DOCTYPE html> <html> <head> <style> #app { height: 400px; } </style> </head> <body> <div id="app"> <!-- <v-chart autoresize :option="myOptions"/> --> </div> <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script> <script> const { createApp, reactive, computed, onMounted } = Vue const app = createApp({ setup() { const state = { myReactiveVar: [{'name': 'foo', 'count': 5}, {'name': 'bar', 'count': 3}, {'name': 'xyz', 'count': 8}] } const myComputedProperty = computed(() => { return state.myReactiveVar.filter(e => e.count <= 5).length; }); onMounted(() => { console.log(myComputedProperty); console.log(myComputedProperty.value); }); return { state, myComputedProperty }; } }) .mount("#app"); </script> </body> </html>
核心原因
这个现象本质是浏览器控制台的对象打印机制导致的,不是Vue本身的bug:
调用console.log打印引用类型(比如对象、数组)时,控制台不会立刻序列化对象内容存快照,只会保存一个对象引用。等你手动在控制台点开这个对象查看属性时,才会实时读取对象当前的属性值展示。
你的场景里,onMounted执行的时机早于axios异步请求返回的时机,此时state.allCvls还是初始空数组,allCvlCount.value是初始值0,所以直接打印allCvlCount.value拿到的就是这个执行瞬间的0值;等你后续在控制台点开打印的computed对象时,axios请求已经完成返回,state.allCvls已经被赋值为接口返回的数组,computed也完成了自动重算,此时读取到的value就是更新后的数组长度,自然和之前打印的瞬时值不一致。
调试排查方向
- 检查
state的响应式定义:你贴的测试用例里state没有用reactive()包裹,实际项目中如果漏写reactive包装,响应式会完全失效,computed不会随数据更新自动重算。 - 加日志核对执行时序:在computed的回调函数里加打印,记录每次重算时的数组长度;同时在axios请求的
then回调、onMounted钩子入口都加打印,标记三个节点的执行顺序,就能明确值变化的时间线。 - 排查响应式丢失问题:检查axios返回后的赋值逻辑,如果
state是通过reactive定义的,要直接给state.allCvls赋值接口返回的数组,不要先把state解构出单独变量再赋值,这种写法会丢失响应式,导致computed无法触发更新。 - 验证时序猜想:在onMounted里等请求完成后再打印值,比如用
await等待axios请求结束后打印allCvlCount.value,或者加2-3秒的延迟setTimeout再打印,此时拿到的值和你展开computed对象看到的值一定是一致的。 - 检查初始值设置:确认
state.allCvls的初始值是空数组[],如果初始值未设置为undefined,首次访问.length会抛出错误,也会导致值异常。
内容的提问来源于stack exchange,提问作者JCm
相关产品推荐
相关产品推荐

