Vuejs - 事件委托和 v-for 上下文引用

Vuejs - Event delegation and v-for context reference

我正在使用以下代码片段来呈现列表:

<div @click.prevent="myhandler($event)"><!-- Delegated event handler-->
    <div class="tasks" v-for="(task, subName) in step.tasks">
        <button type="button">
            {{ task.caption }}
        </button>
        <span> {{ task.callableName }} </span>
    </div>
</div>
methods: {
    myhandler(e){
        // Event target may be a button element.
        let target = e.target;
        // …
        // Let's assume we know 'target' is a button element instance.
        // I wish I could have access to the v-for item ("task") which is associated in some ways to the button that was clicked.
        // let the_task_reference = ?;
    }…

是否有一种简洁的方式让我可以完成与该按钮相关的 v-for 范围特定任务?
谢谢。

最直接的解决方案是将事件处理程序放在与 v-for 指令相同的 div 上,然后只传入 task 变量:

<div 
  class="tasks" 
  v-for="(task, subName) in step.tasks"
  @click.prevent="myhandler(task, $event)"
>
  <button type="button">{{ task.caption }}</button>
  <span>{{ task.callableName }}</span>
</div>

如果您确实需要在父元素上使用事件处理程序,您可以通过组件 属性 跟踪单击的任务,并向 div 添加一个额外的单击处理程序v-for 指令:

<div @click.prevent="myhandler($event)"
  <div 
    class="tasks" 
    v-for="(task, subName) in step.tasks" 
    @click="clickedTask = task"
  >
    <button type="button">{{ task.caption }}</button>
    <span>{{ task.callableName }}</span>
  </div>
</div>

您需要添加 clickedTask 属性:

data() {
  return {
    clickedTask: null,
  }
}

然后在处理程序中,您可以通过 this.clickedTask 引用任务。

另一种方法是将任务索引存储在按钮上。

<div class="tasks" v-for="(task, index) in step.tasks">
    <button type="button" :data-index="index">
        {{ task.caption }}
    </button>
    <span> {{ task.callableName }} </span>
</div>

并在您的处理程序中使用索引获取任务。

myhandler(evt){
  const task = this.step.tasks[evt.target.dataset.index]
  ...
}

Example.

如果你有像 id 这样更强壮的东西,那就更好了。

不推荐

有一个隐藏的 属性, __vue__ 添加到 Vue 和 Component 根元素。如果你迭代一个组件,你将能够做一些事情 like in this example.

我不推荐这种方法,因为它严重依赖于 Vue 内部结构,可能会随着版本的不同而变化,但它现在已经存在。