如何为Vue3禁用状态的按钮添加涟漪效果并启用点击事件?
解决Vue3禁用按钮触发涟漪效果的问题
核心问题是原生disabled属性的按钮会被浏览器拦截点击事件,也无法获取焦点,导致你的涟漪动画触发不了。可以用以下两种方法解决:
方法一:用样式模拟禁用状态(推荐)
不要用原生disabled,而是通过动态类来模拟禁用的视觉效果,这样按钮依然能响应点击和触发涟漪:
<script setup> import { ref } from 'vue' const disableSubmit = ref(true) function handleClick() { // 禁用状态下只触发涟漪,不执行提交逻辑 if (disableSubmit.value) return // 这里写正常的表单提交逻辑 console.log('提交表单') } </script> <template> <button class="btn-ripple" :class="{'btn-disabled': disableSubmit}" @click="handleClick" > <span>Submit</span> </button> </template> <style> .btn-ripple { box-sizing: border-box; border: none; cursor: pointer; color: white; padding: 15px 40px; border-radius: 8px; font-size: 22px; box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); background: #00a1d4; transition: all 0.1s; outline: none; position: relative; overflow: hidden; } /* 模拟禁用状态的视觉样式 */ .btn-disabled { background: #8cc6dc; cursor: not-allowed; box-shadow: none; opacity: 0.7; } .btn-ripple:after { content: ""; position: absolute; top: 50%; left: 50%; width: 5px; height: 5px; background-color: #ffffff; opacity: 0; border-radius: 100%; transform: scale(1, 1) translate(-50%); transform-origin: 50% 50%; } @keyframes ripple { 0% { transform: scale(0, 0); opacity: 1; } 20% { transform: scale(25, 25); opacity: 1; } 100% { opacity: 0; transform: scale(40, 40); } } /* 点击时触发涟漪动画,不受禁用状态影响 */ .btn-ripple:active::after { animation: ripple 1s ease-out; } </style>
方法二:容器包裹按钮,手动触发涟漪
如果必须保留原生disabled属性,可以在按钮外层套一个容器,监听容器的点击事件来手动触发涟漪:
<script setup> import { ref, nextTick } from 'vue' const disableSubmit = ref(true) const triggerRipple = ref(false) async function handleContainerClick() { // 触发涟漪动画 triggerRipple.value = true await nextTick() triggerRipple.value = false } </script> <template> <div class="btn-container" @click="handleContainerClick"> <button :disabled="disableSubmit" class="btn-ripple" :class="{'ripple-active': triggerRipple}" > <span>Submit</span> </button> </div> </template> <style> .btn-container { display: inline-block; cursor: pointer; } .btn-ripple { box-sizing: border-box; border: none; cursor: pointer; color: white; padding: 15px 40px; border-radius: 8px; font-size: 22px; box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); background: #00a1d4; transition: all 0.1s; outline: none; position: relative; overflow: hidden; } .btn-ripple:disabled { background: #8cc6dc; cursor: not-allowed; box-shadow: none; opacity: 0.7; } .btn-ripple:after { content: ""; position: absolute; top: 50%; left: 50%; width: 5px; height: 5px; background-color: #ffffff; opacity: 0; border-radius: 100%; transform: scale(1, 1) translate(-50%); transform-origin: 50% 50%; } @keyframes ripple { 0% { transform: scale(0, 0); opacity: 1; } 20% { transform: scale(25, 25); opacity: 1; } 100% { opacity: 0; transform: scale(40, 40); } } /* 通过动态类触发涟漪 */ .btn-ripple.ripple-active::after { animation: ripple 1s ease-out; } </style>
说明
- 方法一更简洁,既保留了禁用的视觉效果,又能正常触发涟漪,同时避免了原生
disabled的限制。 - 方法二适合必须使用原生
disabled的场景,需要额外的容器和状态来控制动画触发。
内容的提问来源于stack exchange,提问作者Lahiru
相关产品推荐
相关产品推荐

