如何为嵌套v-for创建唯一的引用?

时间:2018-11-17 15:54:32

标签: vue.js v-for

我有一个嵌套的对象数组,像这样:

    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"。但是,每当我尝试通过在v-for div之后添加{{counter++}}来执行此操作时,都会得到一个infite循环。
  3. 还有其他想法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

一种方法是使您的参考文献正常且可排序,然后在参考文献的排序列表中找到您当前的位置,以找出哪个是正确的先前参考文献。

例如,创建一个从索引计算引用的方法,因此您无需重复代码。在这种情况下,我将引用设为“ 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-for:

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