Реализация клавиши Enter для переключения фокуса в Vue

Vue.js
Реализация клавиши Enter для переключения фокуса в Vue

Почти во всех браузерах есть возможность переключать фокус с помощью клавиши Tab.

Но своенравные пользователи настоятельно требуют, чтобы была функция клавиши Enter для переключения фокуса.

Для того, чтобы доставить деньги онлайн, мы должны были принять потребности клиента без каких-либо принципов.

В предыдущем поколении у большинства из них была такая рабочая привычка. Привыкайте называть сохранение как редактирование и привыкайте заменять Tab на Enter. Это результат отравления Microsoft Excel.

Сначала я думал, что эта функция очень проста, не более чем перенос функции клавиши Enter на клавишу Tab, и проблема может быть решена за считанные минуты.

Может быть трудно сразу появиться, я обнаружил, что эта дорога - это тупик.

el.click()Вы можете вызвать событие клики или использоватьdispatchEvent.但是键盘和鼠标事件却不行。

Итак, если вы хотите, чтобы фокус срабатывал не с помощью переключателя клавиши Tab,focusПочти единственный выбор.

Реализуйте клавишу Enter для переключения фокуса на собственных страницах.

Проект основан на vue и element-ui, чтобы сначала прояснить идеи реализации, отложите их на время и найдите ответ на нативной странице.

Ниже приведена собственная html-страница.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Demo</title>
  </head>
  <body>
    <form>
      <input placeholder="姓名" />
      <input placeholder="性别" />
      <input placeholder="年龄" />
    </form>
  </body>
</html>

Дальше будет реализована клавиша Enter для переключения фокуса, я думал гребенка следующая:

  1. Прослушайте событие нажатия клавиши Enter.
  2. Получить текущий сфокусированный элемент.
  3. Получите следующий элемент, который будет сфокусирован.
  4. Переключить фокус.

Идея есть, и реализовать ее очень просто.

1. Прослушайте событие нажатия клавиши Enter

Добавьте тег script в документ и напишите следующий код.

function enterCallback(e) {
  if (e.keyCode === 13) {
    // 按下回车后的逻辑
  }
}
window.addEventListener("keydown", enterCallback);

обращать внимание,enterCallbackВыньте его отдельно и используйте для выхода из события прослушивателя.

Наиболее распространенный способ прослушивания событий нажатия клавиш — использовать делегирование событий для привязки событий кwindowна объекте. По сравнению с методом привязки события к каждому элементу самым большим преимуществом этого метода является экономия памяти и более высокая производительность.

Есть много способов определить, какая клавиша нажата, например,e.key,e.codeилиe.keyCodeи так далее. Но в большинстве случаев рекомендуется использоватьe.keyCode.下面是一张来自网络的keyCodeповерхность.

2. Получить текущий сфокусированный элемент

常见的有两种方式。 Первыйe.targetВторойdocument.activeElement.这种情况下,个人更推荐使用第二种。

function enterCallback(e) {
  if (e.keyCode === 13) {
    let activeEl = document.activeElement;
  }
}

3. Получить следующий элемент для фокусировки

Этот шаг также проще. использоватьel.nextElementSiblingДоступен API.

function enterCallback(e) {
  if (e.keyCode === 13) {
    let activeEl = document.activeElement;
    let nextEl = activeEl.nextElementSibling;
  }
}

4. Переключить фокус

вызов переключения фокусаfocusможет быть достигнут.

function enterCallback(e) {
  if (e.keyCode === 13) {
    let activeEl = document.activeElement;
    let nextEl = activeEl.nextElementSibling;
    nextEl && nextEl.focus();
  }
}

Пока реализовано самое простое Demo, давайте посмотрим на реальную ситуацию в проекте.

Реализуйте клавишу Enter для переключения фокуса в проекте element-ui.

Из-за использования разработки компонентов и таких факторов, как стиль, узел dom не так прост, как нативная демонстрация, написанная выше, и реальная ситуация представляет собой многоуровневую вложенность. Ниже приведена фактическая сгенерированная структура кода.

<div
  class="el-form-item el-form-item--small"
  style="margin-bottom: 0vh; width: 25%; display: inline-block;"
>
  <label for="pactcode" class="el-form-item__label" style="width: 130px;"
    >协议号</label
  >
  <div class="el-form-item__content" style="margin-left: 130px;">
    <div class="el-input el-input--small">
      <!---->
      <input
        type="text"
        autocomplete="off"
        id="el-input"
        placeholder="未填写协议号"
        class="el-input__inner"
      />
      <!---->
    </div>
  </div>
</div>

Можно видеть, что если каждое поле ввода представляет собой вложенную структуру такого типа, описанный выше метод не может быть решен напрямую. потому чтоnextElementSiblingAPI может найти только следующий родственный элемент, а здесь ввод явно не может найти следующий родственный элемент.

Идея состоит в том, чтобы искать внешний слой с помощью поиска с возвратом, пока вы не найдете имя класса, содержащееel-form-itemа такжеel-form-item--smallЭлемент-предок элемента-предка, а затем найдите имя класса из следующего родственного элемента этого элемента-предка.el-input__innerВходные элементы.

Итак, чтобы написать две функции, а именно для поиска элементов-предковfindFormItemfindInput.

найтиформитем:

function findFormItem(el) {
  const parent = el.parentElement;
  if (!parent) return document.body;
  if (
    parent.className.includes("el-form-item") &&
    parent.className.includes("el-form-item--small")
  ) {
    return parent;
  }
  return findFormItem(parent);
}

найтиВвод:

function findInput(container) {
  let nextEl = container.nextElementSibling;
  if (!nextEl) return;
  let input = nextEl.querySelector("input");
  while (input.id === "el-select") {
    nextEl = nextEl.nextElementSibling;
    if (!nextEl) return;
    input = nextEl.querySelector("input");
  }
  if (input.className.includes("el-input__inner")) return input;
}

С помощью этих двух функций очень просто переключить фокус с помощью Enter. Необходимо выполнить всего две строки кода.

const container = findFormItem(document.activeElement);
findInput(container) && findInput(container).focus();

Полный код выглядит так.

существуетmethodsТри метода объявлены в .

methods: {
    addEnterListener() {
      if (window.__completeEnterBind__) return;
      window.addEventListener("keydown", this.enterCallback);
      window.__completeEnterBind__ = true;
    },
    removeEnterListener() {
      window.removeEventListener("keydown", this.enterCallback);
      window.__completeEnterBind__ = false;
    },
    enterCallback(e) {
      function findFormItem(el) {
        const parent = el.parentElement;
        if (!parent) return document.body;
        if (
          parent.className.includes("el-form-item") &&
          parent.className.includes("el-form-item--small")
        ) {
          return parent;
        }
        return findFormItem(parent);
      }
      function findInput(container) {
        let nextEl = container.nextElementSibling;
        if (!nextEl) return;
        let input = nextEl.querySelector("input");
        while (input.id === "el-select") {
          nextEl = nextEl.nextElementSibling;
          if (!nextEl) return;
          input = nextEl.querySelector("input");
        }
        if (input.className.includes("el-input__inner")) return input;
      }
      if (e.keyCode === 13) {
        const container = findFormItem(document.activeElement);
        findInput(container) && findInput(container).focus();
      }
    }
}

затем вmountedДобавить прослушиватель возврата каретки в и вdestroyУберите клавишу Enter из прослушивания.

mounted() {
  this.addEnterListener();
},
destroy() {
  this.removeEnterListener();
},

Следует отметить, что элемент находится в форме страницы с несколькими вкладками, и компонент формы может отображаться несколько раз, поэтому, добавляя окно к объекту__completeEnterBind__поле, чтобы обеспечить правильную привязку событий возврата каретки и перевода строки.

Таким образом, они выполнили конкретные потребности пользователя, от средств проекта, чтобы стать на шаг ближе.

Оригинальный адрес:У-у-у, Лу Чжэньцянь.