el-select框在 @change和remove-tag事件同时使用时,踩过的坑

。。。翻了很多资料,一直没有找到对于el-select框在 @change和remove-tag事件同时使用时,处理事件先后顺序的问题
不过结论是终于解决了(liao)
所以决定把这次的踩坑记录存下来,方便后来者也遇到类似的问题可参考解决方案~
如果后续有问题或者新思路可以联系我哟~

一、踩坑前准备

  1. select 框 可多选
  2. select 框 可进行change事件
  3. select 框 可进行remove事件
  4. 远程(动态接口)获取下拉框数据

二、踩坑描述

  1. 根据每次选中的item数据详情,取到对应的某个属性dataType来做数据校验,由于数据是靠远程搜索的,所以需要定义一个全局变量先来存储该数据值
  2. 新增的情况: 每次取数据的最后一条作为详情,通常会在change事件中来写这部分的逻辑
  3. 编辑的情况:和后端配合完成,后端会返回个类型,从而在前端的角度来讲,也算新增
  4. 删除的情况:踩坑来啦,对于多选的 select 组件,当点击移除标签时,通常会先触发 change 事件,然后触发 remove 事件。这是因为移除标签会导致选中值发生变化,从而触发 change 事件。因为在 change 事件中已经有对数据的最后一条做了写逻辑处理(同2),所以,在删除时,也会走这块逻辑,这样是错误的,本身删除应该走对应remove的逻辑。

三、解决思路

说到这里, 可能迫不及待的想知道如何解决的啦,下面我就简单概括一下:
其实解决方案看着很简单,只是我们不太关注
思路:
为了实现在移除标签时先调用 remove 事件再调用 change 事件,可以使用 Vue 的 $nextTick 方法。以下是一个示例:

  1. 在 Vue 实例的 data 中添加一个标志变量,例如 isRemoving:
data() {
  return {
    isRemoving: false,
    // 其他数据...
  };
},
  1. 在 remove 事件处理函数中,设置 isRemoving 为 true:
methods: {
  keyFieldsRemove() {
    this.isRemoving = true;
    // 其他处理逻辑...
  },
  // 其他方法...
},
  1. 在 change 事件处理函数中,使用 this.$nextTick 将处理逻辑推迟到下一个事件循环,并在处理逻辑执行前检查 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 函数。

你可能感兴趣的:(Vue,vue.js,javascript)