正如 Chris Fritz (Vue.js Core Team Emeriti) 在 VueCONF US 2019 中提到的那样
如果我们让 Kia 输入 .native,然后基本输入的根元素突然从输入变为标签,则此组件已损坏且不明显,事实上,您甚至可能无法立即捕捉到它,除非您有一个很好的测试。相反,通过避免使用 .native 修饰符 我目前认为这是一种反模式,并将在 Vue 3 中删除,您将能够明确定义父级可能关心哪个元素监听器被添加到...
使用 Vue 2
使用$listeners:
因此,如果您使用的是 Vue 2,解决此问题的更好选择是使用 完全透明的包装器 逻辑。为此,Vue 提供了一个 $listeners 属性,其中包含在组件上使用的侦听器对象。例如:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
然后我们只需要将v-on="$listeners" 添加到test 组件中,例如:
Test.vue(子组件)
<template>
<div v-on="$listeners">
click here
</div>
</template>
现在<test> 组件是一个完全透明的包装器,这意味着它可以像普通的<div> 元素一样使用:所有侦听器都可以工作,而无需.native 修饰符。
演示:
Vue.component('test', {
template: `
<div class="child" v-on="$listeners">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @click="testFunction"></test>
</div>
我们也可以使用$emit方法来达到这个目的,它可以帮助我们在父组件中监听子组件的事件。为此,我们首先需要从子组件发出custom event,例如:
Test.vue(子组件)
<test @click="$emit('my-event')"></test>
重要提示:始终使用 kebab-case 作为事件名称。有关更多信息和有关这一点的演示,请查看此答案:VueJS passing computed value from component to parent。
现在,我们只需要在父组件中监听这个发出的自定义事件,比如:
App.vue
<test @my-event="testFunction"></test>
所以基本上,我们将简单地使用v-on:my-event 或@my-event,而不是v-on:click 或简写@click。
演示:
Vue.component('test', {
template: `
<div class="child" @click="$emit('my-event')">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @my-event="testFunction"></test>
</div>
使用 Vue 3
使用v-bind="$attrs":
Vue 3 将在许多方面让我们的生活变得更加轻松。一个例子是,它可以帮助我们创建一个更简单的透明包装器,只需使用v-bind="$attrs",只需使用更少的配置即可。通过在子组件上使用它,我们的监听器不仅可以直接从父组件工作,而且任何其他属性也可以像普通的<div> 一样工作。
所以,关于这个问题,我们不需要在 Vue 3 中更新任何内容,您的代码仍然可以正常工作,因为 <div> 是这里的根元素,它会自动监听所有子事件。
演示 #1:
const { createApp } = Vue;
const Test = {
template: `
<div class="child">
Click here
</div>`
};
const App = {
components: { Test },
setup() {
const testFunction = event => {
console.log("test clicked");
};
return { testFunction };
}
};
createApp(App).mount("#myApp");
div.child{border:5px dotted orange; padding:20px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<test v-on:click="testFunction"></test>
</div>
但是,对于具有嵌套元素的复杂组件,我们需要将属性和事件应用到 <input /> 而不是父标签,我们可以简单地使用 v-bind="$attrs"
演示 #2:
const { createApp } = Vue;
const BaseInput = {
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input v-bind="$attrs">
</label>`
};
const App = {
components: { BaseInput },
setup() {
const search = event => {
console.clear();
console.log("Searching...", event.target.value);
};
return { search };
}
};
createApp(App).mount("#myApp");
input{padding:8px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<base-input
label="Search: "
placeholder="Search"
@keyup="search">
</base-input><br/>
</div>