我理解该函数的作用,但我真的不知道 e.preventDefault() 是做什么的。我知道这可以防止 keydown 事件的默认行为,但我真的不知道那是什么行为,我一直无法找到它。
参考文章:https://hidde.blog/using-javascript-to-trap-focus-in-an-element/
陷阱对焦功能
trapFocus(document.getElementById('dialog-backdrop'));
function trapFocus(element) {
const focusableLms = element.querySelectorAll('a[href]:not([disabled]),button:not([disabled]),textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]),input[type="checkbox"]:not([disabled]), select:not([disabled])');
const firstFocusableLm = focusableLms[0];
const lastFocusableLm = focusableLms[focusableLms.length - 1];
element.addEventListener('keydown', (e) => {
const isTabPressed = (e.key === 'Tab');
if (!isTabPressed) {
return;
}
if (e.shiftKey) /* shift + tab */ {
if (document.activeElement === firstFocusableLm) {
lastFocusableLm.focus();
e.preventDefault();
}
} else /* tab */ {
if (document.activeElement === lastFocusableLm) {
firstFocusableLm.focus();
e.preventDefault();
}
}
});
}
<div id="dialog-backdrop" class="dialog-backdrop">
<div class="alert-dialog" id="alert-dialog" role="alertdialog" aria-label="Confirm discard changes." aria-describedby="alert-dialog__desc">
<img src="img/garbage-collector-2.jpg" alt="" />
<button aria-label="Close dialog." type="button" class="alert-dialog__cancel-btn" id="alert-dialog__cancel-btn">
<span aria-hidden="true" class="material-symbols-outlined">cancel</span>
</button>
<p class="alert-dialog__desc" id="alert-dialog__desc">Are you sure you want to discard all changes made in form?</p>
<div>
<button id="alert-dialog__confirmation-btn" type="button">Yes</button>
<button id="alert-dialog__discard-btn" type="button">No</button>
</div>
</div>
</div>
如果我删除它,它只会捕获对话框中三个按钮元素中的两个的焦点。它完全忽略了关闭按钮。并且仅在“是”和“否”按钮之间循环。
按 Tab 键的默认行为是移至下一个可聚焦的 HTML 元素。就代码而言:
if (document.activeElement === lastFocusableLm) {
firstFocusableLm.focus();
e.preventDefault();
}
如果新/下一个可聚焦元素是
lastFocusableLm
,焦点将更改为 firstFocusableLm
。如果省略 e.preventDefault();
,则默认行为将被应用——即将焦点移动到下一个元素——那么该元素就是 firstFocusableLm
之后的元素。这就是为什么它看起来像是忽略了 firstFocusableLm
又名。关闭按钮。它只跳两次。
调用
e.preventDefault();
将停止 keyup 事件,因此不会继续聚焦下一个元素的操作。