将事件和本地 vue 变量传递给绑定函数的惯用方式

Posted

技术标签:

【中文标题】将事件和本地 vue 变量传递给绑定函数的惯用方式【英文标题】:Idiomatic way of passing both event and local vue variable to bound function 【发布时间】:2019-07-11 06:10:28 【问题描述】:

我试图弄清楚如何将 v-for 成员和原始事件数据访问到 vue.js 中事件的绑定函数,但我终生无法在文档中找到它。

我想要什么:

<div class="card pickup" v-for="pickup in pickups">
        <select v-on:change="locationChanged">

locationChanged 在我的 vue 对象中调用以下方法:

vuePickup = new Vue(
    el: '#pickups',
    data: 
        pickups: pickups,
    ,
    methods: 
        locationChanged: (event, pickup) => 
            pickup.newLocation = event.target.value == -1;
        
    ,
);

这需要访问相关元素和绑定到 v-model 的该部分的对象。

默认情况下,使用v-on:change="locationChanged" 调用locationChanged 和事件,并且可以通过event.target 访问该元素,但我找不到访问pickup 对象的方法,我将特定元素绑定到.

改用v-on:change="locationChanged(pickup)" 会导致locationChanged 被我需要的模型调用,但是我失去了对相关html 元素的引用。

我最终做的是在模型本身中设置一个本地函数来转发值:

v-on:change="e => locationChanged(e, pickup)"

它为我提供了我需要的信息。

但是,我觉得这不是正确的方法,因为 a) 我在文档中找不到它,并且 b) 它不是最用户友好的。

@Lawless 指给我an existing question 的另一个用户更普遍地想知道如何访问事件(与我访问事件目标的目标相比,即触发事件的元素),但我的问题是这里的惯用方法仍然存在,因为这是一个非常基本的问题(枚举元素的回调),但两种解决方案(我的问题和链接的问题)都不是很明显,并且未在 vue.js 手册中涵盖。

vue.js 社区是否更喜欢更惯用的方法?

【问题讨论】:

你试过&lt;select v-on:change="locationChanged($event, pickup)"&gt; 吗?来源 - ***.com/questions/40956671/… Passing event and argument to v-on in Vue.js的可能重复 【参考方案1】:

Another question 在 *** 上(@Lawless 向我指出)问的问题与我一开始提出的问题相同(即,如何在枚举元素的绑定中访问事件数据,而不是与顶部关联的元素) vue.js 对象),提供了另一种更直接(但恕我直言更加神秘)的方法来完成同样的任务。

回顾一下,从 vue.js 生成的 HTML 元素开始,绑定到通过枚举获得的 vuejs 对象

<div class="card pickup" v-for="pickup in pickups">
        <select v-on:change="locationChanged">
            ...
        </select>
</div>

如何访问支持对象(此处为 pickup)和对 select 元素的引用,以便查询其新值并采取相应措施。

我的方法是利用 vuejs 默认传入事件这一事实,并解决如果您使用 lambda 在回调中显式提供本地对象作为参数时 vuejs 抑制事件参数的事实:

<div class="card pickup" v-for="pickup in pickups">
        <select v-on:change="e => locationChanged(e, pickup)">
            ...
        </select>
</div>

以额外的函数调用/间接层为代价,将我感兴趣的元素显式添加到回调中。

The previous answer 提供了一个解决方案,它利用了显式定义的 vuejs $event 变量,该变量始终被转换为本机浏览器事件,除了您希望捕获的任何其他变量之外,还可以直接使用它,使解决方案如下所示:

<div class="card pickup" v-for="pickup in pickups">
        <select v-on:change="locationChanged($event, pickup)">
            ...
        </select>
</div>

这需要更深入的vuejs知识,但避免了闭包。

但是,我一直在搜索,因为我觉得这个解决方案不符合 vuejs 的精神(我所听到的只是每个人都在谈论 vuejs 文档有多棒,但这个答案并没有明确存在,而是必须拼凑起来)。

似乎我正在努力解决一个常见的情况,即知道我想要什么,但不知道如何到达那里。我以前排除 vuejs 的领域知识导致我在我的问题中采用非惯用方法,而不是我如何 会解决这个问题。

最后,我找到了我正在寻找的明显答案,一个感觉像是正确的“vuejs 方式”的答案,以及对我最初问题的正确惯用解决方案:

问题是我将标准的 JS/DOM 内省与 vuejs 模型混合在一起,并且在两者之间的转换中出现了摩擦(泄漏的抽象和所有)。我想要一个 select 元素的本机句柄以及一个 vuejs 对象 (pickup),当我应该做的是专门使用 vuejs 来完成我需要的事情时,最终通过将 select 元素绑定到 vuejs对象/属性,并在我绑定的回调中直接引用它:

<div class="card pickup" v-for="pickup in pickups">
        <select v-model:pickup.location v-on:change="locationChanged(pickup)">
            ...
        </select>
</div>

select 元素现在绑定到我的 vuejs 模型的location 属性,我可以直接在我的locationChanged 处理程序中查询它的状态/值传入我的pickup无需使用$event 或闭包的对象:

let vuePickup = new Vue(
    el: '#pickups',
    data: 
        pickups: pickups,
    ,
    methods: 
        locationChanged: (pickup) => 
            pickup.newLocation = pickup.location == -1;
        
    ,
);

【讨论】:

以上是关于将事件和本地 vue 变量传递给绑定函数的惯用方式的主要内容,如果未能解决你的问题,请参考以下文章

如何按值将变量传递给匿名javascript函数?

将范围传递给回调函数/绑定

将数据从孩子传递给父母,而无需加载事件,这可能在 vue 世界上吗?

Vue 组件之间传参!

vue组件父传子、子传父、兄弟组件之间传值

将 Rust 变量传递给期望能够修改它的 C 函数