需求:
对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