。。。翻了很多资料,一直没有找到对于el-select框在 @change和remove-tag事件同时使用时,处理事件先后顺序的问题
不过结论是终于解决了(liao)
所以决定把这次的踩坑记录存下来,方便后来者也遇到类似的问题可参考解决方案~
如果后续有问题或者新思路可以联系我哟~
踩坑来啦
,对于多选的 select 组件,当点击移除标签时,通常会先触发 change 事件,然后触发 remove 事件。这是因为移除标签会导致选中值发生变化,从而触发 change 事件。因为在 change 事件中已经有对数据的最后一条做了写逻辑处理(同2),所以,在删除时,也会走这块逻辑,这样是错误的,本身删除应该走对应remove的逻辑。说到这里, 可能迫不及待的想知道如何解决的啦,下面我就简单概括一下:
其实解决方案看着很简单,只是我们不太关注
思路:
为了实现在移除标签时先调用 remove 事件再调用 change 事件,可以使用 Vue 的 $nextTick
方法。以下是一个示例:
data() {
return {
isRemoving: false,
// 其他数据...
};
},
methods: {
keyFieldsRemove() {
this.isRemoving = true;
// 其他处理逻辑...
},
// 其他方法...
},
methods: {
keyFieldsChange() {
this.$nextTick(() => {
if (this.isRemoving) {
// 执行 remove 事件相关的处理逻辑...
}
// 执行 change 事件的处理逻辑...
this.isRemoving = false;
});
},
// 其他方法...
},
这样,在移除标签时,remove 事件处理函数将先于 change 事件处理函数执行。
全局定义是否删除
private isRemoving: boolean = false;
这是一个踩坑的select框描述
这是一个change事件处理逻辑,采用$nextTick作为解决方案
private keyFieldsChange(keyFieldsParamsData: string[]) {
this.$nextTick(() => {
console.log('this.isRemoving', this.isRemoving);
if (!this.isRemoving) {
// 执行 remove 事件相关的处理逻辑...
// 以下代码可以忽略 开始
this.isKeyFieldsRemove = false;
const selectedItem =
this.commonCheck(keyFieldsParamsData)?.selectedData;
if (!selectedItem) {
return;
}
console.log('selectedItem', selectedItem);
this.newCopyKeyFields.push(selectedItem);
this.factorLogic.newCopyKeyFields = this.newCopyKeyFields;
this.checkKeyFields(keyFieldsParamsData);
// 以下代码可以忽略 结束
}
// 执行 change 事件的处理逻辑...
this.isRemoving = false;
console.log('======this.isRemoving', this.isRemoving);
});
}
// 以下代码可以忽略 开始
// 取数据的最后一条作为新增详情
private commonCheck(keyFieldsArr: string[]) {
console.log('-keyFieldsArr-', keyFieldsArr);
// 新增数据做校验
const selectedData = keyFieldsArr[keyFieldsArr.length - 1];
console.log('selectedData', selectedData);
// 获取当前选中的数据
const filterItem = this.keyFieldsData.filter(
(item: any) => item.name === selectedData
);
console.log('filterItem', filterItem);
if (!filterItem || filterItem.length === 0) {
return;
}
this.keyFieldsVisibleObj.message = filterItem[0];
const isArray = filterItem[0]?.dataType === 'List';
const isMap = filterItem[0]?.dataType === 'Map';
return {
isArray,
isMap,
selectedData: filterItem[0],
};
}
// 以下代码可以忽略 结束
这是一个删除事件逻辑
private keyFieldsRemove(value: string) {
this.isRemoving = true;
console.log('remove--', value);
// 以下代码可以忽略 开始
this.newCopyKeyFields.forEach((item: KeyFieldsItemType, index: number) => {
if (item.name === value) {
this.newCopyKeyFields.splice(index, 1);
}
});
const isRemove = this.factorLogic.key_fields.some((item: string) => {
return item === value;
});
if (isRemove.length) {
this.isKeyFieldsRemove = true;
}
this.checkIsArray();
// 以下代码可以忽略 结束
}
Vue 的 $nextTick 方法用于在下一个 DOM 更新周期之后执行延迟回调。在修改数据之后,可以使用 $nextTick 来等待 DOM 更新。这在需要在数据变化之后立即操作 DOM 时非常有用。
在 Vue 2 中, $ nextTick 是 Vue 实例的一个方法,可以在组件内部使用 this.$nextTick 调用。以下是一个 Vue 2 的示例:
methods: {
updateData() {
this.message = 'Updated message';
this.$nextTick(() => {
// 在这里执行 DOM 操作,因为此时 DOM 已经更新
console.log('DOM updated');
});
},
},
在 Vue 3 中,$nextTick 被移除了,取而代之的是 nextTick 函数,可以从 vue 包中导入。以下是一个 Vue 3 的示例:
import { ref, nextTick } from 'vue';
export default {
setup() {
const message = ref('Initial message');
const updateData = async () => {
message.value = 'Updated message';
await nextTick();
// 在这里执行 DOM 操作,因为此时 DOM 已经更新
console.log('DOM updated');
};
return {
message,
updateData,
};
},
};
在 Vue 3 的 setup 函数中,可以使用 nextTick 函数并结合 async/await 来实现类似的功能。注意,需要将 updateData 函数声明为 async 函数。