Как создать уникальный ref для вложенного v-for? - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть гнездовой массив объектов, например:

    taskList: [{
      taskName: "Number One"
    },{
      taskName: "Number Two",
      children: [{
        taskName: "Child One"
      },{
        taskName: "Child due"
      }]
    },{
      taskName: "Number Three"
      }]}

Я перебираю этот список с помощью вложенного v-for и создаю вход для каждого элемента, например так:

  <div v-for="(task, index) in taskList">
      <input :ref="'inputField' + index" type="text" v-model="task.taskName" @keydown.up="arrowPress(index, -1)">
      <div v-for="(childOne, childOneIndex) in task.children">
            <input ref="inputField" type="text" v-model="task.taskName" @keydown.up="arrowPress(childOneIndex, -1)">

Я установил событие, которое позволяет мне перемещать фокус вверх / вниз по этим входам с помощью клавиш со стрелками . Метод для этого выглядит так:

      arrowPress(index, value) {
      this.$nextTick(() => this.$refs['inputField'+ (value + index)][0].focus());
      }

Это хорошо работает для родителей.

Но я хочу иметь возможность перемещаться и между детьми. То есть с фокусировкой на «Номер 3», когда я нажимаю вверх, я хочу перейти к «Дитя Два», затем к «Дитя Один», затем к «Номер Два» и т. д.

Я вижу некоторые решения для этого, но не выяснил, как заставить любое из них работать:

  1. Измените :ref="'inputField' + index" на ref="inputField". Но как я тогда узнаю, что inputField вызывает, чтобы изменить его + -1? Например. как перейти от inputField2 к inputField1 в моем методе?
  2. Добавьте общий счетчик, который делает ++ при каждом добавлении ввода, и используйте :ref="'inputField' + counter". Однако всякий раз, когда я пытаюсь сделать это, добавляя {{counter++}} после div v-for, я получаю бесконечный цикл.
  3. Есть еще идеи?

Заранее спасибо!

1 Ответ

0 голосов
/ 17 ноября 2018

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

Например, создайте метод для вычисленияссылка из индексов, поэтому вам не нужно повторять код.В этом случае я сделал ref 'inputFieldXXXXYYYY', где XXXX - родительский индекс, а YYYY - дочерний индекс:

    ref(parent, child) {
        let me = 'inputField' + parent.toString().padStart(4, '0');
        if (child !== undefined) me += child.toString().padStart(4, '0');
        return me;
    },

Затем в вашем шаблоне используйте ref (index) для родителя и ref (index, childIndex) для потомков:

<div id="main">
    <div v-for="(task, index) in taskList">
        <input :ref="ref(index)" type="text" v-model="task.taskName" @keydown.up="arrowPress(index)">
        <div v-for="(child, childIndex) in task.children">
            <input :ref="ref(index, childIndex)" type="text" v-model="task.taskName" @keydown.up="arrowPress(index, childIndex)">
        </div>
    </div>
</div>

Затем в функции arrowPress дети найдены в отсортированном списке в правильном месте, и вы можете уменьшить индекс, чтобы найти предыдущую ссылку:

    arrowPress(parent, child) {
        let refs = Object.keys(this.$refs).filter(key => key.indexOf('inputField') === 0).sort();
        let i = refs.indexOf(this.ref(parent, child));
        i = Math.max(i - 1, 0);
        let prevRef = refs[i];
        this.$nextTick(() => this.$refs[prevRef][0].focus());
    }

Это работает для нажатий вверх.Вы можете видеть, как это будет распространяться на стрелки вниз.

Рабочая скрипка: https://jsfiddle.net/jmbldwn/a1sjk75r/24/

Для комментариев, здесь есть потенциально более простой способ, который включает в себя выравнивание структуры с последующим использованием одного v-для в шаблоне:

https://jsfiddle.net/jmbldwn/u0anzm35/7/

...