Vue.js Element Ui - ловушка / блокировка фокуса при открытом el-диалоге - PullRequest
0 голосов
/ 12 сентября 2018

Как вы можете видеть здесь , когда вы открываете любой пример диалога и начинаете нажимать клавишу табуляции, фокус начинает выделять элементы, которые находятся вне / позади диалога.Мне было интересно, есть ли у element-ui что-то, что я мог бы предложить, что я пропустил, чтобы заметить?

Во всяком случае, сейчас я использую vue-focus-lock , но я бы хотел, чтобы что-то нативное было предложеноelement-ui довольно потянул библиотеку, чтобы решить эту проблему.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Вот ответ на мой собственный вопрос:

Прежде всего я попытался использовать плагин vue-focus-lock, он работает, но также возникают проблемы при выборе таких компонентов, как el-checkbox или el-radio.Вы можете увидеть проблему, когда внешний / задний контент el-dialog больше (ниже сгиба), чем флажок или радио не будут проверены.

В любом случае, вот мое решение, я создал компонент FocusLock.vue:

<template lang="pug">
  div.dialog-focus-lock
    slot
</template>

<script>
export default {
  name: 'focus-lock',

  data() {
    return {
      focusableEls: [],
      firstFocusableEl: [],
      lastFocusableEl: [],
      focusedElBeforeOpen: document.activeElement,
    };
  },

  methods: {
    handleDialogFocusLock() {
      const selectors = '' +
        'a[href], ' +
        'input:not([disabled]), ' +
        'select:not([disabled]), ' +
        'textarea:not([disabled]), ' +
        'button:not([disabled])';

      const getEls = this.$el.querySelectorAll(selectors);

      this.focusableEls = Array.prototype.slice.call(getEls);
      [this.firstFocusableEl] = this.focusableEls; // get first array item
      [this.lastFocusableEl] = this.focusableEls.slice(-1); // get last array item

      this.$el.addEventListener('keydown', e => this.handleKeyDown(e));
      this.firstFocusableEl.focus();
    },

    handleBackwardTab(e) {
      if (document.activeElement === this.firstFocusableEl) {
        e.preventDefault();
        this.lastFocusableEl.focus();
      }
    },

    handleForwardTab(e) {
      if (document.activeElement === this.lastFocusableEl) {
        e.preventDefault();
        this.firstFocusableEl.focus();
      }
    },

    handleKeyDown(e) {
      const KEY_TAB = 9;

      switch (e.keyCode) {
        case KEY_TAB:
          if (this.focusableEls.length === 1) {
            e.preventDefault();
            break;
          }
          if (e.shiftKey) {
            this.handleBackwardTab(e);
          } else {
            this.handleForwardTab(e);
          }
          break;
        default:
          break;
      }
    },
  },

  mounted() {
    this.handleDialogFocusLock();
  },
};
</script>

Я хотел, чтобы компонент был доступен глобально, поэтому импортировал его в main.js или, в вашем случае, просто импортируйте его туда, куда вам нужно.

import FocusLock from '@/components/partials/FocusLock.vue';
Vue.component('FocusLock', FocusLock);

И используя ихвезде, где мне нужно, просто так:

<template lang="pug">
  focus-lock
    el-dialog(:visible.sync="dialogVisible")
      el-form(:model="editedItem")
        // form elements goes here
</template>

Взял некоторую помощь у ЗДЕСЬ .

Кроме того, я думаю, вам не стоит беспокоиться об обработке this.$el.removeEventListener, этоvue.js позаботился о том, чтобы проверить его, вставив приведенный ниже код в консоль браузера и запустив его при открытом el-dialog, и снова запустив при его закрытии.

Array.from(document.querySelectorAll('*'))
  .reduce(function(pre, dom){
    var clks = getEventListeners(dom).click;
    pre += clks ? clks.length || 0 : 0;
    return pre
  }, 0)
0 голосов
/ 12 сентября 2018

Это похоже на ошибку, которую element-ui еще не исправил.Если вы хотите простое нативное решение, вот идея: вы можете прослушивать событие keydown на клавише Tab.В этом случае вы можете получить доступ к последнему элементу (document.activeElement) в диалоговом окне и предотвратить дальнейшие нажатия вкладок.Если вы сделаете это, не забудьте удалить прослушиватель событий при закрытии диалога.Надеюсь, это поможет.

...