问题描述
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>
你期待的结果是什么?实际看到的错误信息又是什么?
开始界面:
点击编辑按钮弹出第一行的数据
点击取消后点击第二行的编辑按钮
点击取消按钮
不知道是哪里出了问题?
在弹窗中修改手机号,表格中的数据竟然同时改变,按照代码逻辑是点击确认后才会修改,而现在是在确认前会同步修改,确认后却变成了原来的数据,一脸懵啊啊啊
输出对象的mobile是最新的值,直接输出对象,其中的mobile是原来的值,应该怎么写才能赋给userList新值呢?
第一个问题
首先要知道,resetField()方法不是将表单重置为空,而是重置为初始值,也就是表单第一次绑定的值。
由于代码中是浅拷贝,导致一个改变,另一个也会跟随变化。引用类型直接赋值相当于共用一个地址,指向同一个堆内存,所以会跟着变。因此在resetFields方法执行时,editUserForm表单中的值变成了初始值,导致userList里的数据也变成了初始值,所以才会点哪一行都会变成第一次点击那行的数据。
第二个问题,弹窗editUserForm变化,表格中userList同时改变,也是因为在editUser方法里用了浅拷贝