Vuex传递state后Getters失效,疑与SensorService.toggleSensor有关
核心原因:直接修改Vuex State的引用类型对象
你在SensorService.toggleSensor里直接操作了传入的selected参数——这个参数是Vuex state中selected的引用,相当于直接修改了Vuex的原始状态对象,而非生成新对象。Vuex依赖引用变化触发状态更新检测,当你把同一个引用的对象提交给mutation时,Vuex会判定状态未发生变化,因此依赖该状态的getters不会重新计算。
而你用硬编码数据时,是创建了全新的对象,引用地址不同,所以能正常触发更新。
代码中的具体错误
语法错误导致逻辑异常:
内层循环里的sensorAlreadySelected;是无效代码,没有给变量赋值为true,导致sensorAlreadySelected始终为false,后续的传感器添加逻辑会出错。正确写法应为:sensorAlreadySelected = true;直接修改原state对象:
你在SensorService.toggleSensor中直接对selected(即state.selected的引用)执行Vue.delete、push、属性赋值等操作,违反了Vuex“状态变更必须通过mutation”的规范,同时破坏了状态的可追踪性和变更检测机制。
修复方案
方案1:创建state对象的副本,操作副本后返回
在SensorService.toggleSensor开头,先对传入的selected做深拷贝(因为是嵌套对象),后续操作全部基于副本进行:
async toggleSensor(selected, sensor) { // 深拷贝原对象,避免修改state的引用 const newSelected = JSON.parse(JSON.stringify(selected)); let deviceId = await store.dispatch('chart/getDeviceIdBySensorId', sensor.id); let deviceAlreadySelected = false; let sensorAlreadySelected = false; for (let devId in newSelected) { if (devId === deviceId) { deviceAlreadySelected = true; for (let i = 0; i < newSelected[deviceId].length; i++) { if (newSelected[deviceId][i].id === sensor.id) { sensorAlreadySelected = true; // 修复语法错误 Vue.delete(newSelected[deviceId], i); } } } } if (! deviceAlreadySelected) { newSelected[deviceId] = [sensor]; } if (! sensorAlreadySelected && deviceAlreadySelected) { newSelected[deviceId].push(sensor); } return newSelected; },
方案2:在Action中先拷贝state对象再传入
如果不想修改Service层代码,也可以在Action里先拷贝state.selected再传给Service:
async toggleSensor({ state, commit }, sensor) { // 先拷贝state对象 const selectedCopy = JSON.parse(JSON.stringify(state.selected)); let selected = await SensorService.toggleSensor(selectedCopy, sensor); console.log(selected); await commit('updateSelected', selected); },
补充:更优雅的深拷贝方式(可选)
如果你的对象包含JSON.parse(JSON.stringify())无法处理的类型(如Date、函数),可以使用Vue提供的Vue.util.extend或者lodash的_.cloneDeep工具进行深拷贝。
内容的提问来源于stack exchange,提问作者Petar Vasilev

