导言:
在做若依二次开发时遇到个没见过的bug,用了一些时间排,发现有自己没学过的东西。所以记录一下。后端用的是c#的asp.net core
问题描述:
后端穿过来的有数据的参数(数组)roleIds在控制台打印为空
后端字段定义:
后端数据:
前端方法:
在...\src\views\system\user\index.vue的修改按钮
/** 修改按钮操作 */
handleUpdate(row) {
console.log("row",row);
this.reset();
const userID = row.userID || this.ids;
console.log("修改按钮操作userID",userID);
// getUserProfile(userID).then(response => {
GetUserUpdateInfo(userID).then(response => {
console.log("用户修改responseresponse",response);
this.form = response.data;
this.postOptions = response.posts;
this.roleOptions = response.roles;
// this.$set(this.form, "postIds", response.postIds);
this.$set(this.form, "roleIds", response.roleIds);
this.open = true;
this.title = "修改用户";
this.form.password = "";
});
},
打印与问题:
控制台网络
拦截器打印:
在...\src\utils\request.js
// 响应拦截器
service.interceptors.response.use(res => {
console.log("响应拦截器",res);
...
方法响应值打印:
...
// getUserProfile(userID).then(response => {
GetUserUpdateInfo(userID).then(response => {
console.log("用户修改responseresponse",response);
...
可以看到,在控制台的网络中后端传来的roleIds数组是有值的,但是在拦截器和方法响应数据中却变成了空数组。
解决过程:
有仔细检查过整个流程,确认了不是后端问题。也有尝试跟踪过从后端到前端拦截器过程数据的变化,但很少有这方面的经验,也没找到问gpt给的三个情况的执行顺序:
1.浏览器控制台中网络模块检测到请求的返回值并展示。
2.前端定义的拦截器接收响应并打印到控制台。
3.请求方法接收到响应数据并打印完整响应对象。
之后想着把名字换换,我c,又有数据了,猜测是若依对roleIds字段做了些事。
后面排到了,发现这个
this.$set(this.form, "roleIds", response.roleIds);
在...\src\views\system\user\index.vue的修改方法里,把它注释掉之后即使名字还是roleIds,也能展示出数据
/** 修改按钮操作 */
handleUpdate(row) {
console.log("row",row);
this.reset();
const userID = row.userID || this.ids;
console.log("修改按钮操作userID",userID);
// getUserProfile(userID).then(response => {
GetUserUpdateInfo(userID).then(response => {
console.log("完整响应对象:", response);
this.form = response.data.data;
// this.postOptions = response.posts;
this.roleOptions = response.data.roles;
// this.$set(this.form, "postIds", response.postIds);
// this.$set(this.form, "roleIds", response.roleIds);
...
.....很神奇
this.$set()介绍:
this.$set()
是 Vue.js 提供的一个方法,用于向 Vue 实例的响应式对象中动态添加新属性。这在 Vue 的响应式系统中非常重要,因为 Vue 默认只会对已存在的属性进行观察,如果直接赋值新属性,Vue 无法自动检测到这个变化。
this.$set(target, propertyName, value);
- target: 目标对象,通常是 Vue 组件的
data
中的对象。 - propertyName: 要添加的属性名,可以是字符串或符号。
- value: 要设置的值。
注意事项
-
响应式系统:
- 使用
this.$set()
可以确保新添加的属性是响应式的。如果直接用this.user.age = 25
,Vue 不会检测到age
的变化。
- 使用
-
避免性能问题:
- 过多地使用
this.$set()
会增加 Vue 实例的复杂性和性能开销,因此应尽量在需要时使用。
- 过多地使用
-
数组的响应式更新:
- 对于数组,Vue 也提供了一些特定的方法来确保响应式更新,例如
this.$set(array, index, value)
可以用来替代array[index] = value
。
- 对于数组,Vue 也提供了一些特定的方法来确保响应式更新,例如
-
兼容性:
this.$set()
是 Vue 2.x 的方法。在 Vue 3.x 中,由于其响应式系统的改进,使用reactive
和ref
方式进行状态管理,不再需要使用this.$set()
。
-
异步更新:
- 在 Vue 中,数据的更新是异步的,因此在更新后立即访问新的属性时,可能需要使用
nextTick
来确保 DOM 已更新。
- 在 Vue 中,数据的更新是异步的,因此在更新后立即访问新的属性时,可能需要使用
具体原因
还没搞清楚,应该和同步异步有关。具体的话等以后有时间了在看看吧。如果有大佬知道的也可以指点一下。
解决:
将this.$set();注释掉,直接赋值即可
/** 修改按钮操作 */
handleUpdate(row) {
console.log("row",row);
this.reset();
const userID = row.userID || this.ids;
console.log("修改按钮操作userID",userID);
// getUserProfile(userID).then(response => {
GetUserUpdateInfo(userID).then(response => {
console.log("完整响应对象:", response);
this.form = response.data.data;
// this.postOptions = response.posts;
this.roleOptions = response.data.roles;
console.log("this.roleOptions",this.roleOptions);
//这里直接赋值
this.form.roleIds = response.data.roleIds
// this.$set(this.form, "postIds", response.postIds);
// this.$set(this.form, "roleIds", response.roleIds);
this.open = true;
this.title = "修改用户";
this.form.password = "";
});
}