Vue项目Vuex中store.state.activities.list有数据但访问返回空数组
问题成因
这个现象是两个问题叠加导致的,和深浅拷贝操作无关:
- 浏览器控制台对引用类型值存在惰性求值机制:执行
console.log(store.state.activities)时,控制台不会立刻序列化对象内容存储,只会保留该对象的内存引用。你后续在控制台手动展开对象看到的属性值,是你展开对象时刻的最新值,根本不是console.log代码执行瞬间的状态,这也是为什么你会看到对象里list有3条数据的错觉。 - 代码执行时序不匹配:你执行
console.log(store.state.activities.list)、做深浅拷贝的时机,早于list被赋值为业务数据的时机。绝大多数场景下,list的3条业务数据来自接口异步请求,你在请求发出后、响应返回前就读取了list值,拿到的永远是初始化时的空数组;等异步响应返回后,你才把3条数据赋值给store.state.activities.list(替换了list原有的空数组引用),这时候再回去展开之前打印的activities对象,看到的就是赋值后的新list,但之前已经打印、拷贝过的旧空数组不会被更新。 - 极小概率是违反Vuex响应式规则:如果你在mutation函数外部直接修改state,或者给state.activities新增了未在state初始化时预先声明的属性,会导致Vue无法追踪状态更新,但从你描述的现象看基本可以排除这个原因。
修复方案
- 先排除控制台的误导:不要直接打印对象判断状态值,在读取list的位置执行
console.log(JSON.parse(JSON.stringify(store.state.activities))),这行代码会立刻序列化当前对象,拿到的是代码执行瞬间的真实值,执行后即可确认打印时list确实是空数组,不存在“值存在但读不到”的情况。 - 调整依赖逻辑的执行时机:所有依赖
store.state.activities.list的业务逻辑,必须放到list赋值完成之后执行。如果数据来自异步接口,把依赖逻辑移到接口请求的await之后、或者mutation提交完成的回调中,不要在应用初始化阶段同步读取异步更新的状态。 - 严格遵循Vuex状态修改规范:所有state的修改必须通过mutation提交,不要在组件、action里直接给state赋值,参考写法:
// store 定义 const state = { activities: { list: [], dictionaries: {} } } const mutations = { SET_ACTIVITIES_LIST(state, payload) { state.activities.list = payload } }
- 组件中使用状态时优先用计算属性读取,不要在
created/mounted钩子中同步取初始值存到本地变量:
computed: { activityList() { return this.$store.state.activities.list } }
计算属性会自动追踪响应式状态变化,当list被赋值后会自动触发视图更新,不需要手动监听或提前取值。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

