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

Posted

技术标签:

【中文标题】Vuejs - 事件委托和 v-for 上下文引用【英文标题】:Vuejs - Event delegation and v-for context reference 【发布时间】:2017-10-10 18:47:58 【问题描述】:

我正在使用以下 sn-p 来呈现列表:

<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 范围特定任务? 谢谢。

【问题讨论】:

【参考方案1】:

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

<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 内部结构,可能会因版本而异,但它今天就存在。

【讨论】:

我就是这么想的。我可能会去,因为似乎没有其他整洁的选择。我会让这个问题再多活一天,并将您的答案视为解决方案。谢谢。【参考方案2】:

最直接的解决方案是将事件处理程序放在与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>

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

<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 引用任务。

【讨论】:

谢谢,但我知道。正如我所提到的,我需要在这里使用事件委托。换句话说,我希望第一个共同祖先来处理事件,这意味着当我只能访问作为事件目标的按钮元素时,我需要一种方法来引用任务对象。 @Stphane 无法从其范围之外的事件直接访问task 变量。您需要设置一个额外的参考。查看我的更新 我认为 vue 实例上的一些隐藏属性会有所帮助,但似乎这样的事情不存在。我担心您的最终解决方案会导致过多的开销。首先,因为仍然会在每个 v-for div 元素上注册一个点击处理程序(我想首先避免),其次需要一个新的代理数据。我会深入研究,让你知道我最终得到了什么。再次感谢您。

以上是关于Vuejs - 事件委托和 v-for 上下文引用的主要内容,如果未能解决你的问题,请参考以下文章

Vuejs v-for 根据某些条件添加标签属性或事件监听器

委托和事件

委托Lambda表达式和事件

使用 Vuejs 嵌套 v-for 循环

VueJS 和嵌套的 v-for:如何通过每个循环获取端点数据?

Vuejs 使用 v-for 添加和删除类