如何改变所有按钮的点击行为?

欧雷 发表于

问题描述

被人问了这样一个问题——

现在有这样一个场景,所有的按钮(除了查询按钮),在点击的时候,如果该用户使用时间过期了,就要统一弹框提醒,不走按钮原有的方法了

——算是一个项目组的某个前端

问题分析

像这类「把所有……都……」的需求,需要一个汇总通道才能做,也就是说,所有分散的逻辑最终都会经过同一个点才能做管控,就像集散中心一样。

遇到这类需求,首先去想需求中涉及的点都可以通过什么进行汇总,然后在那个汇总的地方统一处理。这样就可使业务代码整洁、易懂,方便维护。

其实,这可以看作是面向切面编程(AOP)中的「切面」。

解决方案

事件代理

在页面加载完时给 body 加上 click 事件监听器,注意要在捕获阶段,这样可以比按钮本身的事件先执行。

click 事件触发后,从触发事件的元素开始沿 DOM 树向上查找代表「按钮」的节点,直到找到或到达 body 节点为止。

在找到代表「按钮」的节点以后,如果文本中包含「查询」就放行,否则检测用户时间是否过期。

function findButton(el) {
  // 向上递归查找
}

function isExpired() {
  // 判断是否过期
}

document.body.addEventListener('click', evt => {
  const button = findButton(evt.target);

  if (button && button.innerText.replaceAll(/\s+/g, '') !== '查询' && isExpired()) {
    alert('您已过期');

    evt.preventDefault();
    evt.stopPropagation();
  }
}, true);

Monkey patch

自定义一个按钮组件以替换原来的,针对 click 事件和子节点做判断,逻辑与上面的事件代理大体相同。

创作不易,若给你提供了价值,还请不吝欧雷充电

左为微信,右为支付宝;充电累计 ¥88 以上可在付款时备注或邮件告知昵称和需要被链接的网址,会列在「赞助」页。其他方式与具体规则请见「资助」。

本文采用知识共享署名-非商业性使用 4.0 国际许可协议,可自由转载、引用,但需署名作者并注明文章出处且不能用于商业用途。

目录