Vue3 自定义指令 v-blur 解决 Element-Plus 按钮点击后变色,需要点击别的地方颜色才能还原的问题

问题背景

button 组件在点击时会获得焦点,如果设置了 :focus 的css样式,则在点击按钮后按钮会改变为相应的样式,直到点击其他的元素,使当前 button 失去焦点,此时按钮会回复样式。

element-plus 等组件库的 button 组件在点击时,都设计成聚焦 button 颜色变浅。如图所示:

本是组件设计者为了交互上的友好,做的特殊的精心设计。但还是有很多测试觉得这是个bug,按钮点击后,颜色应该理解还原,不能保持变色的状态。

很蛋疼,只能解决问题了。

问题分析

这个问题出现的原因,主要是组件库已经给el-button:focus 预设好了 ,只要el-button组件被点击后,处于聚焦状态,那就有显示对应的样式。所以说,要么覆写组件的:focus 样式,要么,就点击按钮的时候,写程序让其点击后立即失焦

解决方案

1. 覆写组件样式

这种方案我没试过,网上有一些这种实现的。

看完网上的例子,我直接舍弃了这个方案。原因有三,

  • 覆写样式实现相当麻烦,而且要保证你覆写的风格能跟原始的样式完全一致;
  • 同时还要考虑组件的 primary,success,warning 等不同的类型的按钮的样式覆写;
  • 当你的系统是自定义按钮的颜色风格时,可能得针对你自己系统的UI风格做处理;

这样考虑下来,就很大程度的破坏了原生组件封装好的UI设计。

2. 自定义一个指令,监听按钮的 click 事件,使元素主动失焦

为什么不是监听 focus 事件?

这里监听 focus 事件也是可以实现相同效果的,但是考虑到主要是为了解决buttonclick事件的交互问题,不应该扩大影像范围。像其他的交互实现的聚焦,会造成聚焦失败, 如,键盘操作聚焦,这时候用户可能会需要知道当前焦点的位置,就不应该主动失焦。

具体实现:

  • 定义指令 v-blur
ts 复制代码
// main.ts
import { createApp, type DirectiveBinding, type VNode } from 'vue'
import App from './App.vue'
const app = createApp(App)

const elBlur = (el: HTMLElement) => {
  return () => el?.blur()
}

app.directive('blur', {
    created (el: HTMLElement, binding: DirectiveBinding, vnode: VNode) {
        if (vnode?.type === 'button') {
          el.addEventListener('click', elBlur(el))
        }
    },
    unmounted (el: HTMLElement) {
        el.removeEventListener('click', elBlur(el))
    }
})
app.mount('#app')
  • 使用指令
html 复制代码
<template>
    <el-button type="primary" v-blur>Primary</el-button>
    <el-button type="success" v-blur>Success</el-button>
    <el-button type="warning" v-blur>Warning</el-button>
</template>

优势:

  • 使用简单,添加一个指令即可实现;
  • 灵活,就跟使用一个 el-button 一样方便,想用就用,不想用也没关系;
  • 必须要覆写组件逻辑, 对 element-plus 组件没有破坏性;

演示效果

相关推荐
kyriewen1 小时前
你的前端滤镜慢得像PPT?用Rust+WebAssembly,一秒处理4K图
前端·rust·webassembly
kyriewen111 小时前
你等的Babel编译,够喝三杯咖啡了——用Rust重写的SWC,只需眨个眼
开发语言·前端·javascript·后端·性能优化·rust·前端框架
IT_陈寒1 小时前
SpringBoot自动配置坑了我,原来要这样绕过去
前端·人工智能·后端
东方小月2 小时前
Claude Code 完整上手指南:MCP、Skills、第三方模型配置一次搞定
前端·人工智能·后端
XZ探长2 小时前
基于 Trae Solo 移动办公修复 Vue3 前端服务问题
前端
逍遥德2 小时前
AI时代,计算机专业大学生学习指南
java·javascript·人工智能·学习·ai编程
蝎子莱莱爱打怪2 小时前
Claude Code 省 Token 小妙招:RTK + Caveman 组合拳
前端·人工智能·后端
Rkgua2 小时前
JS中模拟函数重载的使用
javascript·jquery
竹林8182 小时前
用 wagmi v2 和 Next.js 14 硬扛 NFT 市场前端:从合约调用失败到批量上架,我踩了这些坑
javascript·next.js
Momo__3 小时前
Vue 3.6 Vapor Mode:跳过虚拟 DOM,性能极致优化
前端·vue.js