vue使用elementui中弹出框点击取消触发resetFileds方法后改变了初始数据

问题描述

vue+elementui,dialog中有form,不论是否修改数据都点击取消,触发form的resetFileds方法,但是每点击一个不同的行,那一行的数据就会变成第一次点击打开弹窗的数据

问题出现的环境背景及自己尝试过哪些方法

看到在源码中执行完watch队列后就数据就变了,但是并没有地方去修改原数据

相关代码

 <template>
  <div class="user-container">
    <!--面包屑-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!--卡片视图区域-->
    <el-card class="box-card">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-input placeholder="请输入搜索内容" v-model="queryInfo.query" clearable @clear="getUserList">
            <el-button slot="append" icon="el-icon-search" @click="getUserList($event)"></el-button>
          </el-input>
        </el-col>
        <el-col :span="3">
          <el-button type="primary" @click="addUserVisible=true">添加用户</el-button>
        </el-col>
      </el-row>

      <!--表格区域-->
      <el-table :data="userList" stripe border style="width: 100%">
        <el-table-column type="index"></el-table-column>
        <el-table-column prop="username" label="姓名"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <el-table-column prop="mobile" label="电话"></el-table-column>
        <el-table-column prop="role_name" label="角色"></el-table-column>
        <!--作用域插槽-->
        <el-table-column label="状态">
          <template slot-scope="scope">
            <el-switch v-model="scope.row.mg_state" @change="userStateChange(scope.row)"></el-switch>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template slot-scope="scope">
            <!--修改-->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="mini"
              @click="editUser(scope.row.id)"
            ></el-button>
            <!--删除-->
            <el-button type="danger" icon="el-icon-delete" size="mini"></el-button>
            <!--分配权限-->
            <el-tooltip effect="dark" :enterable="false" content="分配权限" placement="top">
              <el-button type="warning" icon="el-icon-setting" size="mini"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>

      <!--分页-->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryInfo.pagenum"
        :page-sizes="[1, 2, 3, 4]"
        :page-size="queryInfo.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>
    <!--添加用户弹框-->
    <el-dialog title="添加用户" :visible.sync="addUserVisible" @close="addUserFormClose">
      <el-form
        :model="addUserForm"
        :rules="addUserFormRule"
        ref="addUserFormRef"
        label-width="70px"
      >
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addUserForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="addUserForm.password"></el-input>
        </el-form-item>
        <el-form-item label="手机号" prop="mobile">
          <el-input v-model="addUserForm.mobile"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addUserForm.email"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="addUser">确 定</el-button>
      </span>
    </el-dialog>
    <!--修改用户-->
    <el-dialog title="修改用户" :visible.sync="editUserVisible" @close="editUserFormClose">
      <el-form
        :model="editUserForm"
        :rules="editUserFormRule"
        ref="editUserFormRef"
        label-width="70px"
      >
        <el-form-item label="用户名" prop="username">
          <el-input v-model="editUserForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="手机号" prop="mobile">
          <el-input v-model="editUserForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="editUser">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  validatePass,
  validateEmail,
  validatePhone
} from '../../../plugins/validate.js'
export default {
  data() {
    return {
      userList: [],
      // 获取用户的参数列表
      queryInfo: {
        query: '',
        pagesize: 2,
        pagenum: 1
      },
      // 总条数
      total: 0,
      // 添加用户弹框
      addUserVisible: false,
      // 添加用户信息
      addUserForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      // 输入校验
      addUserFormRule: {
        username: [
          { required: true, message: '请输入用户名称', trigger: 'blur' },
          { min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { validator: validatePass, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { validator: validatePhone, trigger: 'blur' }
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: validateEmail, trigger: 'blur' }
        ]
      },
      // 修改弹窗
      editUserVisible: false,
      editUserForm: {},
      editUserFormRule: {
        mobile: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { validator: validatePhone, trigger: 'blur' }
        ]
      }
    }
  },
  created() {
    this.getUserList()
  },
  methods: {
    async getUserList(e) {
      var { data: res } = await this.$http.get('/users', {
        params: this.queryInfo
      })
      if (res.meta.status !== 200)
        return this.$message.error('获取用户列表失败')
      this.userList = res.data.users
      this.total = res.data.total

      // 搜索按钮
      if (e) {
        this.$message.success('查询成功')
      }
    },
    // 监听pagesize改变
    handleSizeChange(newsize) {
      this.queryInfo.pagesize = newsize
      this.getUserList()
      console.log(`每页面${newsize}`)
    },
    // 监听页码
    handleCurrentChange(newnum) {
      this.queryInfo.pagenum = newnum
      this.getUserList()
      console.log(`当前${newnum}`)
    },
    // 修改用户状态
    userStateChange(userinfo) {
      console.log(userinfo)
      userinfo.mg_state = !userinfo.mg_state
      this.$message.error('修改失败')
      //   var { data: res } = await this.$http.put(
      //     `/users/${userinfo.id}/state/${userinfo.mg_state}`
      //   )
      //   if (res.status !== 200) {
      //     userinfo.mg_state = !userinfo.mg_state
      //     return this.$message.error('修改失败')
      //   }
    },
    // 关闭添加用户弹窗
    addUserFormClose() {
      // 清除校验
      this.$refs.addUserFormRef.resetFields()
    },
    // 新增用户
    addUser() {
      // 先验证
      this.$refs.addUserFormRef.validate(valid => {
        if (!valid) return this.$message.error('添加失败')
        // 用post,这里直接在已有数据中添加一项
        console.log(this.addUserForm)
        //this.getUserList()
        this.addUserVisible = false
      })
    },
    // 修改用户
    editUser(id) {
      // 获取这个id的数据
      this.editUserForm = this.userList.find(item => {
        return item.id == id
      })
      this.editUserVisible = true
    },
    editUserFormClose() {
      this.$refs.editUserFormRef.resetFields()
    },
    editUserInfo() {
     this.$refs.editUserFormRef.validate(valid => {
        if (!valid) return
        // 发起put请求
        // 把弹框中的值放入 userList 中
        this.userList.find((item, index) => {
          if (item.id == this.editUserForm.id) {
            this.$set(item, 'mobile', this.editUserForm.mobile)
            //item.mobile = this.editUserForm.mobile
            console.log(item.mobile)
            console.log(item)
            //this.userList.splice(index, 1, item)
            return true
          }
        })
        this.$message.success('修改成功')
        this.editUserVisible = false
  }
}
</script>
<style lang="scss" scoped>
</style>

你期待的结果是什么?实际看到的错误信息又是什么?

开始界面:
image.png
点击编辑按钮弹出第一行的数据
image.png
点击取消后点击第二行的编辑按钮
image.png
点击取消按钮
image.png

不知道是哪里出了问题?

在弹窗中修改手机号,表格中的数据竟然同时改变,按照代码逻辑是点击确认后才会修改,而现在是在确认前会同步修改,确认后却变成了原来的数据,一脸懵啊啊啊
image.png

image.png

image.png
输出对象的mobile是最新的值,直接输出对象,其中的mobile是原来的值,应该怎么写才能赋给userList新值呢?

阅读 5.4k
3 个回答
✓ 已被采纳新手上路,请多包涵

第一个问题
首先要知道,resetField()方法不是将表单重置为空,而是重置为初始值,也就是表单第一次绑定的值。
由于代码中是浅拷贝,导致一个改变,另一个也会跟随变化。引用类型直接赋值相当于共用一个地址,指向同一个堆内存,所以会跟着变。因此在resetFields方法执行时,editUserForm表单中的值变成了初始值,导致userList里的数据也变成了初始值,所以才会点哪一行都会变成第一次点击那行的数据。

this.editUserForm = this.userList.find(item => {
    return item.id == id
})

第二个问题,弹窗editUserForm变化,表格中userList同时改变,也是因为在editUser方法里用了浅拷贝

  这个问题的本质是因为编辑时,第一次打开dialog的时候给表单绑定的model赋值了,
这时候这个model的初始值就变成了赋值的值
  所以resetFields的时候,会将model对应的每个值重置到初始值,
  这时候的初始值就是编辑时赋值的那个值,而不是在data里声明的初始值
  解决方式是,
  等dialog已经初始化mounted之后再给model赋值,也就是
  this.$nextTick(() => { 
    // 这里开始赋值 this.model.xxx = xxx;
    })
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题