禁用 el-radio-group 的方向键切换

群里有人提了这个问题,问他的代码怎么不生效:
e90aab3ce7e3149baea27c178b8d6b1.png

解决过程

我的第一反应是,这应该是浏览器的默认行为,于是写了个 demo,关键点:

  • **keydown **而不是 keyup
  • preventDefault 来阻止浏览器默认行为
1
2
3
4
5
6
7
8
9
10
11
12
group.addEventListener(
"keydown",
function (e) {
console.log("bubble in group");
if (
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].indexOf(e.code) > -1
) {
e.preventDefault();
}
},
false
);

发过去之后,他改成了 keydown 还是不行,于是我在 ElementUI 中试验了一下,它的组件上确实不行。
看了源码发现,ElementUI 在 el-radio-group 上做了 keydown 事件处理,可能是为了保证浏览器的一致性。
怎样绕过它的事件处理函数呢?

ElementUI demo

1
2
3
4
5
6
7
<template>
<el-radio-group v-model="radio" @keydown.capture.stop.prevent>
<el-radio :label="3">Option A</el-radio>
<el-radio :label="6">Option B</el-radio>
<el-radio :label="9">Option C</el-radio>
</el-radio-group>
</template>

关键点:使用 capture 让自己的 handler 先于 Element 的 handler 执行,stop 让这个事件停止传播,那么他设在冒泡阶段的 handler 就不会执行了,再加 prevent 是阻止浏览器默认的键盘移动行为

事件模型

https://javascript.info/bubbling-and-capturing
复习一下事件模型,事件的传播分为三个阶段:

  • 捕获阶段:从根元素到目标元素(事件实际触发的元素)的过程
  • 目标阶段:目标元素
  • 冒泡阶段:从目标元素到根元素

addEventListener

elm.addEventListener('click', (e) => {}, true)表示“当点击事件在捕获阶段传播到 elm 元素上时执行该函数”

stopPropagation

阻止当前事件在上述三个阶段中的传播。
若在捕获阶段途中调用stopPropagation,那么该事件在后续捕获阶段、目标阶段以及冒泡阶段的监听函数都不会执行。
demo

stopImmediatePropagation

区别:

  • stopPropagation:当前阶段、当前目标上的所有监听器都处理完之后才会停止 (stop once it has finished processing all the event listeners on the current target in the **current phase **)
  • stopImmediatePropagation: 同一个目标、同一个阶段上的多个监听器,会按照它们添加的顺序依次执行。调用后后添加的监听器不会执行。(stop right away. no other event listener will be called)

学习利器:可视化工具

https://domevents.dev/
例子: