前言:今天在学习过程中用到了Element-Plus + Vue3.2来开发一个管理系统,但是在用户表格的增删改查的开发中,表格中的单条数据的编辑问题困扰了我,一开始是用ref()取定义了一个currentRow对象(单条数据)

详细见:https://element-plus.gitee.io/zh-CN/component/table.html#%E5%8D%95%E9%80%89

后面在编辑的时候发现不对劲,每次编辑完再重新请求数据的时候会报下面的错误。

然后在网上找了好久也没找出解决方案来,打断点Debug弄了一个小时感觉应该是ref()它的这个问题。我指定ref()它定义了响应式的属性,

而ref()所定义的属性的更改是对变量进行了类似浅拷贝的操作,可能因为在重新请求数据库数据的时候,ref()所定义的currentRow失去了值变为null,具体是为什么我也不知道,虽然这个错误并没有影响页面的增删改查,还是没有问题,但是我觉得这样还是有点问题。

所以我改成用reactive()来定义这个currentRow,但是呢,用reactive()定义的数据再更改的时候,页面没有跟着一起渲染,这样就引出了问题了。

而reactive()则是类似深拷贝,如果重新赋值,就会丢失原来响应式对象的引用地址,变成一个新的引用地址,这个新的引用地址指向的对象是没有经过 reactive 方法处理的,所以是一个普通对象,而不是响应式对象

解决方案

我的操作的是直接用Object.assign()来解决赋值不渲染的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 单条的表格数据,单选
var currentRow = reactive({
id : 100 ,
username : '',
password : '',
nickname : '',
email : '',
phone : '',
address : '',
})
function TableCurrentChange(val : User){
// 这样给reactive赋值可以保证页面会重新渲染
Object.assign(currentRow,val)
}

除此之外呢,还有另外的方法

在定义reactive的时候,定义属性名,在后期赋值的时候,对属性名进行赋值

比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default {
components:{HelloWorld},
name: 'App',
setup(){
let A=reactive({
name:{}
})
const getA= (data)=>{
A.name=data
}
return {
getA,
A
}
}
}

另外就是我用的Object.assign()方法,

Object.assign()拷贝的是属性值,如果源对象的属性值是一个指向对象的指针,那也只拷贝那个指针。

所以如果对象的属性值为基础类型,对于通过Object.assign()拷贝的那个属性而言是深拷贝;如果对象的属性值为引用,对于通过通过Object.assign()拷贝的那个属性而言其实是浅拷贝的。