首页 > 解决方案 > 为什么方向键导航在反转方向时会返回错误的值?

问题描述

我正在尝试使用 keydown 事件创建由箭头键控制的列表导航。选择按预期工作,直到用户反转方向。例如,如果用户在第 3 项上并点击向下箭头,则转到第 4 项。但是,如果用户然后按向上箭头,而不是返回第 3 项,则转到第 5 项。向上箭头的行为符合预期。只有在改变方向时,第一次按键才会产生不正确的结果。

谁能告诉我这是为什么?

function keyListener() {
  "use strict";
  let index = 1;

  document
    .querySelector(".select__element")
    .addEventListener("keydown", (e) => {
      let keyValue = e.key;
      // ****************************** ARROW UP
      if (keyValue === "ArrowUp") {
        console.log("Arrow Up Pressed");

        const selectItem = document.querySelectorAll(".select__item");
        const length = selectItem.length - 1;

        // dropdown the list
        document
          .querySelector(".select__list")
          .classList.add("select__list--visible");

        let indexPrev = index - 1;
        if (indexPrev < 0) {
          indexPrev = length;
        }

        let indexNext = index + 1;
        if (indexNext > length) {
          indexNext = 0;
        }
        // test the bounds
        if (index < 0) {
          index = length;
          indexPrev = length - 1;
          indexNext = 0;
        }

        if (index > length) {
          index = 0;
          indexPrev = index + 1;
          indexNext = length;
        }

        console.log(
          "Up Arrow: ",
          indexPrev,
          index,
          indexNext,
          "Values should decrease"
        );
        // select the item
        selectItem[index].classList.add("select__item--selected");

        selectItem[indexPrev].classList.remove("select__item--selected");
        selectItem[indexNext].classList.remove("select__item--selected");

        index--;
      }

      // ****************************** ARROW DOWN
      if (keyValue === "ArrowDown") {
        console.log("Arrow Down Pressed");

        const selectItem = document.querySelectorAll(".select__item");
        const length = selectItem.length - 1;

        // dropdown the list
        document
          .querySelector(".select__list")
          .classList.add("select__list--visible");

        let indexPrev = index - 1;
        if (indexPrev < 0) {
          indexPrev = length;
        }

        let indexNext = index + 1;
        if (indexNext > length) {
          indexNext = 0;
        }

        // test the bounds
        if (index < 0) {
          index = length;
          indexPrev = 0;
          indexNext = length - 1;
        }

        if (index > length) {
          index = 0;
          indexPrev = length;
          indexNext = index + 1;
        }

        console.log(
          "Down Arrow: ",
          indexPrev,
          index,
          indexNext,
          "Values should increase"
        );

        //select the item
        selectItem[index].classList.add("select__item--selected");

        selectItem[indexPrev].classList.remove("select__item--selected");
        selectItem[indexNext].classList.remove("select__item--selected");

        index++;
      }

    });


}

keyListener();
.select__item--selected,
.select__item:hover {
  background: #25A0DA;
  color: #fff;
}

.select__root {
  background-color: lightpink;
}
<div class="m-wrapper">
  <div id="Select-Pages" class="select">
    <div class="select__element" tabindex="0">
      <div class="select__root">Select an item...</div>
      <ul class="select__list">
        <li class="select__item select__item--selected">Item-1</li>
        <li class="select__item">Item-2</li>
        <li class="select__item">Item-3</li>
        <li class="select__item">Item-4</li>
        <li class="select__item">Item-5</li>
        <li class="select__item">Item-6</li>
      </ul>
    </div>
  </div>

标签: javascripthtmlcssnavigationkeydown

解决方案


修改类列表index变量会递增和递减。因此,突出显示与所选索引不同步。我建议在类列表之前更新变量,如下所示。

此外,由于selectItem数组索引从零开始,我建议定义index = 0.

function keyListener() {
  "use strict";

  const selectItem = document.querySelectorAll(".select__item");
  const length = selectItem.length;
  let index = 0;

  document
    .querySelector(".select__element")
    .addEventListener("keydown", (e) => {

      let keyValue = e.key;

      // store last index
      let lastIndex = index;

      // decrement / increment index
      if (keyValue === "ArrowUp") {
        index--;
      }
      if (keyValue === "ArrowDown") {
        index++;
      }

      // keep index within range
      index = (index + length) % length;

      // deselect last item
      selectItem[lastIndex].classList.remove("select__item--selected");

      // select current item
      selectItem[index].classList.add("select__item--selected");

    });

}

keyListener();
.select__item--selected,
.select__item:hover {
  background: #25A0DA;
  color: #fff;
}

.select__root {
  background-color: lightpink;
}
<div id="Select-Pages" class="select">
  <div class="select__element" tabindex="0">
    <div class="select__root">Select an item...</div>
    <ul class="select__list">
      <li class="select__item select__item--selected">Item-1</li>
      <li class="select__item">Item-2</li>
      <li class="select__item">Item-3</li>
      <li class="select__item">Item-4</li>
      <li class="select__item">Item-5</li>
      <li class="select__item">Item-6</li>
    </ul>
  </div>
</div>


推荐阅读