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

演示效果

相关推荐
Lhuu(重开版1 分钟前
JS:正则表达式和作用域
开发语言·javascript·正则表达式
荔枝一杯酸牛奶1 小时前
HTML 表单与表格布局实战:两个经典作业案例详解
前端·html
Charlie_lll1 小时前
学习Three.js–纹理贴图(Texture)
前端·three.js
yuguo.im2 小时前
我开源了一个 GrapesJS 插件
前端·javascript·开源·grapesjs
安且惜2 小时前
带弹窗的页面--以表格形式展示
前端·javascript·vue.js
摘星编程3 小时前
用React Native开发OpenHarmony应用:NFC读取标签数据
javascript·react native·react.js
GISer_Jing3 小时前
AI驱动营销:业务技术栈实战(From AIGC,待总结)
前端·人工智能·aigc·reactjs
GIS之路5 小时前
GDAL 实现影像裁剪
前端·python·arcgis·信息可视化
AGMTI5 小时前
webSock动态注册消息回调函数功能实现
开发语言·前端·javascript
码界奇点5 小时前
基于SpringBoot+Vue的前后端分离外卖点单系统设计与实现
vue.js·spring boot·后端·spring·毕业设计·源代码管理