如何避免数据跟着一块变呢?

  1. 输入新的姓名和年龄
  2. 提交
  3. 点击过滤(此时你刚刚添加的姓名和年龄出现在了最终的结果中)
  4. 此时,如果你修改上面输入框中的内容,下面结果中对应的内容也会发生变化

这是为什么呢?该如何修改才能使在修改上面输入框中的内容时,下面结果中对应的内容不发生变化呢?

注:这里的persons可以看作是一个存储在服务端数据库中的大数据。

<script setup lang="ts">
import { ref, version as vueVersion, reactive, toRaw } from 'vue'
import { version as epVersion } from 'element-plus'
import { ElementPlus } from '@element-plus/icons-vue'
import {ElMessage} from "element-plus";
const form = reactive({
  name: "",
  age: "",
})
const formRef = ref(null);

async function submit(formInstance) {
  if(!formInstance) return;
  await formInstance.validate((valid) => {
    if(valid) {
      console.log("valid success");
      ElMessage({
        message: "添加成功",
        type: "success"
      })
      persons.push(toRaw(form));
    }else {
      console.log("valid failed");
    }
  })
}
function reset(formInstance) {
  if(!formInstance) return;
  formInstance.resetFields();
}

const persons = [{name: "peter", age: "18"}, {name: "Tom", age: "22" }];

const filterForm = reactive({
  name: ""
});
const filterPersons = ref();
function filter() {
  const result = persons.filter(person => filterForm.name === "" || person.name === filterForm.name);
  console.log("result: ", result);
  filterPersons.value = result;
}
filter();
</script>

<template>
  <h2>添加新数据</h2>
  <el-form :model="form" ref="formRef">
    <el-form-item prop="name">
      <el-input v-model="form.name" placeholder="请输入你的名字"></el-input>
    </el-form-item>
    <el-form-item prop="age">
      <el-select v-model="form.age" clearable>
        <el-option v-for="age in 18" :value="age"></el-option>
      </el-select>
    </el-form-item>
    
    <el-form-item>
      <el-button @click="submit(formRef)" type="primary">提交</el-button>
      <el-button @click="reset(formRef)">重置</el-button>
    </el-form-item>
  </el-form>

  <h2>过滤数据</h2>
  <el-form :model="filterForm">
    <el-row :gutter="10">
      <el-col :span="12">
        <el-form-item clearable>
          <el-input prop="name" placeholder="姓名"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item>
          <el-button @click="filter">过滤</el-button>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
  <h2>结果</h2>
  <el-table :data="filterPersons">
    <el-table-column prop="name" label="姓名"></el-table-column>
    <el-table-column prop="age" label="年龄"></el-table-column>
  </el-table>

</template>

element plus playground

image.png

阅读 1.3k
4 个回答

persons.push(toRaw(form))因为你push的数据是form,而你下面修改的数据也是form,这是同一份数据,所以会一起变。你应该拷贝一份数据进行push比如使用JSON序列化persons.push(JSON.parse(JSON.stringify(form)))

看到第 21 行:

      persons.push(toRaw(form));

formObject,所以这一行是把 form 的引用放进 persons 里了,所以 persons 里的 form同一个对象,具体可以搜 JavaScript 引用

所以这样改:

     if(valid) {
       console.log("valid success");
       ElMessage({
         message: "添加成功",
         type: "success"
       })
-      persons.push(toRaw(form));
+      persons.push({ ...toRaw(form) });
     }else {
       console.log("valid failed");
     }

上面这个是浅拷贝,用于 form 只有一层对象的情况({ a: 1, b: 2 })。如果 form 有对象套对象({ a: { b: 1 }, c: 2 }),用:

persons.push(structuredClone(toRaw(form)));

看看 structuredClone 的兼容性表,如果要兼容不支持的浏览器,搜一下

你直接深拷贝一个form,再push进去。
就是这里出了问题 persons.push(toRaw(form));

我的做法就是在点编辑的时候把当前的对象复制一下

JSON.parse(JSON.stringify(persons[index]));

推荐问题
宣传栏