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

演示效果

相关推荐
aklry几秒前
uniapp三步完成一维码的生成
前端·vue.js
Rubin938 分钟前
判断元素在可视区域?用于滚动加载,数据埋点等
前端
爱学习的茄子8 分钟前
AI驱动的单词学习应用:从图片识别到语音合成的完整实现
前端·深度学习·react.js
用户3802258598249 分钟前
使用three.js实现3D地球
前端·three.js
程序无bug11 分钟前
Spring 面向切面编程AOP 详细讲解
java·前端
zhanshuo11 分钟前
鸿蒙UI开发全解:JS与Java双引擎实战指南
前端·javascript·harmonyos
JohnYan11 分钟前
模板+数据的文档生成技术方案设计和实现
javascript·后端·架构
撰卢35 分钟前
如何提高网站加载速度速度
前端·javascript·css·html
10年前端老司机40 分钟前
在React项目中如何封装一个可扩展,复用性强的组件
前端·javascript·react.js
Struggler28143 分钟前
解决setTimeout/setInterval计时不准确问题的方案
前端