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

演示效果

相关推荐
一位正在转型AI全栈的前端工程师13 分钟前
AI 全栈学习之旅 - Week2:从零搭建一个可部署的 AI 聊天应用
前端
aixingpan36 分钟前
aixingpan.cn API开发文档:api_docs_trichart_natal_solararc_transit2接口指南
前端·php
Ayayoyo41 分钟前
公平随机转盘的前端实现:Web Crypto API、拒绝采样与加权抽取
前端
GitLqr1 小时前
提升 Web 开发效率:我常用的 10 个 TypeScript 实战技巧
vue.js·react.js·typescript
程序员黑豆1 小时前
鸿蒙应用开发:@Link 装饰器实现父子组件双向同步
前端·后端·harmonyos
前端炒粉1 小时前
简易实现ssr
开发语言·前端·javascript
顶级自由人2 小时前
【前端菜鸟的补课01】Zod 与 PostgreSQL 全栈数据工程教学
前端·后端·程序员
swipe2 小时前
11|(前端转全栈)购物车不能只存在前端:用户维度数据如何在后端落库
前端·后端·全栈
meilindehuzi_a3 小时前
Node.js + LangChain.js + Milvus 实战:从 EPUB 入库到《天龙八部》RAG 问答系统
javascript·langchain·node.js
勇往直前plus3 小时前
Vue3(篇四)单页面应用到路由管理
javascript·typescript·前端框架·vue