【Vue3】防止在使用v-for生成的多个按钮组件中的双击操作

需求

v-for生成的每个按钮做防止双击的处理,用于防止用户误操作或消除操作延迟产生的问题。

方法1

最快速的方法就是简单粗暴遍历列表在里面添加一个参数,用来判断按钮的状态。这个方法一般不建议!

比如下面的一段代码,有一个oldList的数组,里面包含了3个按钮(1、2、3)。然后遍历一遍数据,添加上判断按钮状态的参数status

给按钮绑定一个handleButtonClick()方法。它首先将对应按钮设置为禁用状态,然后在500毫秒后通过setTimeout将其再设置回可点击状态

<template>
  <div>
    <button
        v-for="(item, i) in list"
        :key="i"
        @click="handleButtonClick(i)"
        :disabled="item.status"
    >

    Button {{ item.val }} {{item.status}}
    </button>
  </div>

</template>

<script lang='ts' setup>
import { reactive} from "vue";
/
/ 按钮的列表
const oldList = ref([1, 2, 3]);
/
/遍历成新的数组
const list = reactive(
    oldList.value.map((val) => ({
      val: val,
      status: false,
    }))
);

const handleButtonClick = (i) => {
  list[i].status = true;
  setTimeout(() => {
    list[i].status = false;
  }, 500);
};

</
script>

方法2

通过创建新对象来修改和更新的按钮状态。

如下面的代码,通过ref()创建了一个响应式引用isDisabled,用于保存每个按钮的状态,初始值设置为可点击的。

绑定点击事件handleButtonClick(),它首先将对应按钮设置为禁用状态,然后在500毫秒后通过setTimeout将其再设置回可点击状态。

为什么要创建一个新对象呢?

原因是:Vue 不能检测到数组内对象属性的变化并触发视图更新。所以我们需要创建一个新的对象,代替直接修改对象的属性,这样可以让 Vue 的响应式系统知道有变化发生。

<template>
  <div>
    <button
        v-for="(item, i) in list"
        :key="item"
        @click="handleButtonClick(i)"
        :disabled="isDisabled[i].status"
    >

      Button {{ item }} {{isDisabled[i].status}}
    </button>
  </div>

</template>

<script lang='ts' setup>
import { ref } from "vue";

/
/ 按钮的列表
const list = ref([1, 2, 3]);
/
/ isDisabled,保存每个按钮的状态
const isDisabled = ref(list.value.map(() => ({ status: false }))); 

const handleButtonClick = (i) => {
  isDisabled.value[i] = { ...isDisabled.value[i], status: true }; /
/ 创建一个新的对象

  setTimeout(() => {
    isDisabled.value[i] = { ...isDisabled.value[i], status: false }; /
/ 创建一个新的对象
  }, 500);
};
</
script>

方法3

使用ref 属性为每一个按钮创建一个引用。(极力推荐)

  • 创建按钮子组件

我们先来创建一个按钮的子组件CustomButton.vue:

首先创建一个响应式引用isDisabled,初始值为false。定义了一个setDisabled函数,这个函数修改了isDisabled的值。

然后通过defineExpose函数来暴露setDisabled函数,使得它可以在组件的外部被调用。

<script setup>
import { ref } from 'vue';
const isDisabled = ref(false);

async function setDisabled(value{
  isDisabled.value = value
}

defineExpose({ setDisabled });
</script>

<template>
  <button
      @click="setDisabled(true)"
      :disabled="isDisabled"
  ><slot /
></button>
</
template>

  • 父组件

如下面的代码,通过ref()创建了一个响应式引用buttonRef,用于保存所有按钮的引用。

绑定点击事件handleButtonClick,在事件中使用 buttonRef.value[i].setDisabled(false)来使按钮恢复为可以被点击的状态。这里要注意的是 buttonRef.value[i] 是一个对按钮元素的引用,我们在子组件中增加了 setDisabled 方法,所以可以直接调用这个方法来改变按钮的状态。

onBeforeUpdate生命周期函数在组件更新前清空buttonRef数组,以保证组件更新时能获取到最新的引用。

<template>
  <div>
    <CustomButton
        v-for="(item, i) in list"
        :key="item"
        @click="handleButtonClick(i)"
        :ref="el => { if (el) buttonRef[i] = el }"
    >
      Button {{ item }}
    </CustomButton>
  </div>
</template>

<script lang='ts' setup>
import {reactive,ref,onBeforeUpdate} from "vue";
//按钮的列表
const list = reactive([1, 2, 3]);
const buttonRef = ref([]);
onBeforeUpdate(() => {
  buttonRef.value = [];
});

const handleButtonClick = (i) => {
  setTimeout(() => {
    buttonRef.value[i].setDisabled(false);
  }, 500)
};
</script>


原文始发于微信公众号(大前端编程教学):【Vue3】防止在使用v-for生成的多个按钮组件中的双击操作

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/286487.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!