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 组件没有破坏性;

演示效果

相关推荐
Shi_haoliu6 小时前
openClaw源码部署-linux
前端·python·ai·openclaw
程序员小寒7 小时前
前端性能优化之白屏、卡顿指标和网络环境采集篇
前端·javascript·网络·性能优化
烛阴7 小时前
Claude CLI AskUserQuestion 工具详解:让 AI 开口问你
前端·claude
wal13145207 小时前
OpenClaw教程(九)—— 彻底告别!OpenClaw 卸载不残留指南
前端·网络·人工智能·chrome·安全·openclaw
mon_star°8 小时前
在TypeScript中,接口MenuItem定义中,为什么有的属性带问号?,有的不带呢?
前端
牛奶8 小时前
分享一个开源项目,让 AI 辅助开发真正高效起来
前端·人工智能·全栈
次顶级9 小时前
表单多文件上传和其他参数处理
前端·javascript·html
kuntli9 小时前
Vue生命周期全解析
vue.js
why技术9 小时前
我拿到了腾讯QClaw的内测码,然后沉默了。
前端·后端