Vue3 + Pinia:子组件修改 Pinia 数据,竟然影响了原始数据?

1、业务场景

在组件通信中,我们经常遇到这样的需求:

  • 表格中的每一行都有一个"编辑"按钮
  • 点击按钮,打开弹窗,展示该行数据用于编辑
  • 修改完成后提交,或取消编辑

初始实现代码

1️、父组件中使用 Pinia 设置当前行数据
javascript 复制代码
// store/station.ts
export const useStationStore = defineStore('station', () => {
  const rowData = ref<RowType>({
    name: '',
    id: '',
    // ...
  })

  const setRowData = (row: RowType) => {
    rowData.value = row //  注意这里
  }

  return { rowData, setRowData }
})
2、父组件中点击编辑按钮
ini 复制代码
const edit = (row: RowType) => {
  stationStore.setRowData(row)
  visible.value = true
}
3、子组件中直接使用 rowData
arduino 复制代码
const { rowData } = storeToRefs(useStationStore())

// 在表单中双向绑定使用
<el-input v-model="rowData.name" />

好像到这里一切都没有问题,当我们点击编辑、修改数据的时候,就会发现 表格中的原始数据被修改了,我们分析一下原因

引用传递 + 响应式副作用

ini 复制代码
rowData.value = row

这里做的是引用赋值,也就是说:

  • rowData.valuerow 指向同一块内存
  • 子组件改 rowData.value.xxx,就是在改原始 row.xxx
  • Vue 的响应式系统会让一切看起来都"流畅同步",但这不一定是你想要的!
正确做法:使用深拷贝隔离数据

这里不做第三方库的推荐,自行查找,也不建议自己手写,寻找一个好的轮子会事半功倍。这边主要介绍的是思路。

一些"取巧"的办法

1、如果你的数据只是修第一层,浅拷贝就可以解决 如:

javascript 复制代码
row = JSON.parse((JSON.stringify(row)))
Object.assign(form.value, stationStore.rowData)

2、如果要深层上面的这两个方法就无法保证数据不会被修改

欢迎大家留言探讨你们的实践经验,如有疏漏或不妥之处,欢迎在评论区指出,互相学习,共同进步!

相关推荐
朱昆鹏4 分钟前
开源 Claude Code + Codex + 面板 的未来vibecoding平台
前端·后端·github
lyrieek9 分钟前
pgadmin的导出图实现,还在搞先美容后拍照再恢复?
前端
小书包酱11 分钟前
在 VS Code中,vue2-vuex 使用终于有体验感增强的插件了。
vue.js·vuex
永远是我的最爱14 分钟前
基于.NET的小小便利店前台收银系统
前端·sqlserver·.net·visual studio
从文处安15 分钟前
「九九八十一难」第一难:前端数据mock指南(TS + VUE)
前端
Zhencode35 分钟前
Vue3 响应式依赖收集与更新之effect
前端·vue.js
x-cmd39 分钟前
[x-cmd] jsoup 1.22.1 版本发布,引入 re2j 引擎,让 HTML 解析更安全高效
前端·安全·html·x-cmd·jsoup
天下代码客1 小时前
使用electronc框架调用dll动态链接库流程和避坑
前端·javascript·vue.js·electron·node.js
weixin199701080161 小时前
【性能提升300%】仿1688首页的Webpack优化全记录
前端·webpack·node.js
冰暮流星1 小时前
javascript之数组
java·前端·javascript