为什么 v-on doen 在外部模板中使用 Vue 组件时不起作用?



情况

假设我有一个组件BaseButton它只是一个围绕<button>元素的简单包装器:

Vue.component('base-button', {
template: `
<button>
<slot />
</button>
`
});

使用该按钮时,我需要将处理程序绑定到此按钮上的单击事件:

<base-button @click="handler">
Click me
</base-button>

带有上述代码的笔

问题所在

上述解决方案不起作用。处理程序根本不会触发。

有人可以解释我为什么吗?我猜处理程序在被组件模板替换之前绑定到元素,但这只是一个猜测 - 我在 vue.js 文档中找不到任何关于它的内容。除了那个文档 州:

非 prop 属性是传递给组件的属性, 但没有定义相应的道具。

虽然明确定义的道具是传递信息的首选 对于子组件,组件库的作者不能总是 预见可能使用其组件的上下文。那是 为什么组件可以接受任意属性,这些属性被添加到 组件的根元素。

@click(v-on:click(在我看来是一个非道具属性,根据上面的文本应该被继承。但事实并非如此。

道具解决方案

我知道我可以声明一个 prop 并将处理程序传递给组件内部(下面的代码(。然后它按预期工作。

对我来说,这个解决方案的问题在于我对处理程序的声明方式没有精细的控制。如果在一次使用BaseButton时我想在@click上使用怎么办 Vue.js 公开的一些事件修饰符(例如.stop.prevent.capture(?我必须使用另一个道具(如capture(并使用v-if,但它会使组件模板非常混乱。如果我将处理程序保留在模板中,在使用它的地方,我可以根据需要以干净灵活的方式修改事件声明。

Vue.component('base-button', {
prop: {
clickHandler: {
type: Function,
required: true
}
},
template: `
<button>
<slot />
</button>
`
});
<base-button :click-handler="handler">
Click me
</base-button>

v-on指令在普通/原生 DOM 元素或 Vue 自定义元素组件上使用时的行为不同,如 API 文档中所述:

当用于普通元素时,它只侦听本机 DOM 事件。在自定义元素组件上使用时,它会侦听在该子组件上发出的自定义事件

在您的情况下,您将它应用于自定义<base-button>元素组件,因此它将仅侦听自定义事件,即您在此组件实例上显式$emit的事件。

来自底层<button>的本机"click"事件冒泡阶段不会触发@click侦听器...

。除非使用.native修饰符:

.native- 侦听组件根元素上的本机事件。

Vue.component('base-button', {
template: `
<button>
<slot />
</button>
`
});
new Vue({
el: '#app',
data: {
handler(event) {
console.log('submit from where the component was used');
//console.log(event);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<base-button @click.native="handler">
Click
</base-button>
</div>

最新更新