正如Chris Fritz (Vue.js核心团队Emeriti)在VueCONF US 2019中提到的那样
如果我们让Kia输入。native然后基输入的根元素从input变成了label突然这个组件就坏了,这并不明显事实上,你可能不会马上发现它除非你有一个很好的测试。相反,通过避免使用.native修饰符,我目前认为这是一种反模式,并将在Vue 3中删除,您将能够显式地定义父元素可能关心添加到哪个元素监听器…
使用Vue 2
使用美元的听众:
因此,如果您正在使用Vue 2,解决这个问题的更好选择是使用完全透明的包装器逻辑。为此,Vue提供了一个$listeners属性,其中包含组件上使用的侦听器对象。例如:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
然后我们只需要在测试组件中添加v-on="$listeners",如下所示:
测试。Vue(子组件)
<template>
<div v-on="$listeners">
click here
</div>
</template>
现在<test>组件是一个完全透明的包装器,这意味着它可以像正常的<div>元素一样使用:所有的侦听器都可以工作,不需要.native修饰符。
演示:
Vue.component(“测试”,{
模板:
<div class="child" v-on="$listeners">
点击这里
< / div >”
})
新Vue ({
埃尔:“# myApp”,
数据:{},
方法:{
testFunction:函数(事件){
console.log(测试点)
}
}
})
Div.child{边框:5px虚线橙色;填充:20 px;}
< script src = " https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js " > < /脚本>
< div id =“myApp”>
<测试@click = " testFunction " > < /测试>
< / div >
使用$emit方法:
我们还可以使用$emit方法来实现这个目的,它可以帮助我们侦听父组件中子组件的事件。为此,我们首先需要从子组件中发出一个自定义事件,例如:
测试。Vue(子组件)
<test @click="$emit('my-event')"></test>
重要提示:始终使用串大小写作为事件名称。有关这一点的更多信息和演示,请查看这个答案:VueJS将计算值从组件传递给父组件。
现在,我们只需要监听父组件中发出的自定义事件,比如:
App.vue
<test @my-event="testFunction"></test>
所以基本上,我们不用v-on:click或者简写@click,而是用v-on:my-event或者@my-event。
演示:
Vue.component(“测试”,{
模板:
<div class="child" @click="$emit('my-event')" >
点击这里
< / div >”
})
新Vue ({
埃尔:“# myApp”,
数据:{},
方法:{
testFunction:函数(事件){
console.log(测试点)
}
}
})
Div.child{边框:5px虚线橙色;填充:20 px;}
< script src = " https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js " > < /脚本>
< div id =“myApp”>
<测试@my-event = " testFunction " > < /测试>
< / div >
使用Vue 3
使用v-bind = " $ attrs”:
Vue 3将在许多方面使我们的生活更容易。例如,它将帮助我们创建一个更简单的透明包装器,配置更少,只需使用v-bind="$attrs"。通过在子组件上使用这个,不仅我们的侦听器可以直接从父组件工作,而且任何其他属性也可以像正常的<div>一样工作。
因此,关于这个问题,我们不需要更新Vue 3中的任何内容,您的代码仍然可以正常工作,因为<div>是这里的根元素,它将自动侦听所有子事件。
示例# 1:
const {createApp} = Vue;
const Test = {
模板:
< div class = "孩子" >
点击这里
< / div >”
};
const App = {
组件:{Test},
设置(){
const testFunction = event => {
console.log(点击“测试”);
};
返回{testFunction};
}
};
createApp (App) .mount(“# myApp”);
Div.child{边框:5px虚线橙色;填充:20 px;}
< script src = " / / unpkg.com/vue@next " > < /脚本>
< div id =“myApp”>
<测试v:点击= " testFunction " > < /测试>
< / 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>