我正在創建一個 Web 組件,給定一個可聚焦的元素串列,它會自動具有可訪問的鍵盤導航。
其中一部分是讓活動元素滾動到視圖中(如果它還沒有的話),為此我使用的是Element.scrollIntoViewIfNeeded(在 chrome 中,所以支持應該不是問題)。
我正在經歷一些奇怪的行為,我無法弄清楚。我創建了一個最小的代碼沙箱來顯示問題。
const app = document.getElementById("app");
for (var i = 0; i < 100; i ) {
const paragraph = document.createElement("p");
paragraph.innerHTML = "element " i;
paragraph.tabIndex = -1;
app.appendChild(paragraph);
}
const handleKeyDown = (event) => {
event.preventDefault();
switch (event.key) {
case "ArrowDown":
if (app.contains(document.activeElement)) {
const next = document.activeElement.nextElementSibling;
next.focus();
next.scrollIntoViewIfNeeded(false);
} else {
const first = app.firstElementChild;
first.focus();
first.scrollIntoViewIfNeeded(false);
}
break;
case "ArrowUp":
if (app.contains(document.activeElement)) {
const previous = document.activeElement.previousElementSibling;
previous.focus();
previous.scrollIntoViewIfNeeded(false);
} else {
const last = app.lastElementChild;
last.focus();
last.scrollIntoViewIfNeeded(false);
}
break;
default:
break;
}
};
document.addEventListener("keydown", handleKeyDown, false);
body {
font-family: sans-serif;
}
.app {
display: flex;
flex-direction: column;
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app" class="app"></div>
<script src="src/index.js"></script>
</body>
</html>
這個centerIfNeeded論點似乎根本沒有得到尊重。有時它會在我第一次關注視口之外的元素時受到尊重,但不是第二次,有時它會被完全忽略。
這是預期的行為嗎?
uj5u.com熱心網友回復:
問題是,默認情況下,focus()呼叫本身會在內部呼叫scrollIntoView(),并且這兩個呼叫會發生沖突。
為防止這種情況,您可以將{ preventScroll: true }選項傳遞給您對focus().
const app = document.getElementById("app");
for (var i = 0; i < 100; i ) {
const paragraph = document.createElement("p");
paragraph.innerHTML = "element " i;
paragraph.tabIndex = -1;
app.appendChild(paragraph);
}
const handleKeyDown = (event) => {
event.preventDefault();
switch (event.key) {
case "ArrowDown":
if (app.contains(document.activeElement)) {
const next = document.activeElement.nextElementSibling;
next?.focus({ preventScroll: true });
next?.scrollIntoViewIfNeeded(false);
} else {
const first = app.firstElementChild;
next?.focus({ preventScroll: true });
first?.scrollIntoViewIfNeeded(false);
}
break;
case "ArrowUp":
if (app.contains(document.activeElement)) {
const previous = document.activeElement.previousElementSibling;
previous?.focus({ preventScroll: true });
previous?.scrollIntoViewIfNeeded(false);
} else {
const last = app.lastElementChild;
last?.focus({ preventScroll: true });
last?.scrollIntoViewIfNeeded(false);
}
break;
default:
break;
}
};
document.addEventListener("keydown", handleKeyDown, false);
body {
font-family: sans-serif;
}
.app {
display: flex;
flex-direction: column;
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app" class="app"></div>
<script src="src/index.js"></script>
</body>
</html>
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/426153.html
標籤:javascript dom js-scrollintoview
上一篇:從React組件中呼叫函式
