Wie von Chris Fritz ( Vue.js Kernteam Emeriti ) in VueCONF US 2019 erwähnt
Wenn wir Kia eingeben lassen .native
und dann das Stammelement der Basiseingabe von einer Eingabe in eine Beschriftung geändert wird, ist diese Komponente plötzlich defekt und es ist nicht offensichtlich, und tatsächlich können Sie sie möglicherweise nicht sofort erfassen, es sei denn, Sie haben einen wirklich guten Test. Wenn Sie stattdessen vermeiden, dass der .native
Modifikator verwendet wird, von dem ich derzeit annehme, dass ein Anti-Pattern in Vue 3 entfernt wird, können Sie explizit definieren, dass es dem übergeordneten Element wichtig sein könnte, welche Element-Listener zu ...
Mit Vue 2
Verwenden von $listeners
:
Wenn Sie also Vue 2 verwenden, ist die Verwendung einer vollständig transparenten Wrapper- Logik eine bessere Option, um dieses Problem zu beheben . Zu diesem Zweck stellt Vue eine $listeners
Eigenschaft bereit, die ein Objekt von Listenern enthält, die für die Komponente verwendet werden. Beispielsweise:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
und dann müssen wir v-on="$listeners"
der test
Komponente nur noch Folgendes hinzufügen :
Test.vue (untergeordnete Komponente)
<template>
<div v-on="$listeners">
click here
</div>
</template>
Jetzt ist die <test>
Komponente ein vollständig transparenter Wrapper , was bedeutet, dass sie genau wie ein normales <div>
Element verwendet werden kann: Alle Listener funktionieren ohne den .native
Modifikator.
Demo:
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>
Mit $emit
Methode:
Zu $emit
diesem Zweck können wir auch eine Methode verwenden, mit der wir Ereignisse von untergeordneten Komponenten in übergeordneten Komponenten abhören können. Dazu müssen wir zuerst ein benutzerdefiniertes Ereignis von einer untergeordneten Komponente wie folgt ausgeben :
Test.vue (untergeordnete Komponente)
<test @click="$emit('my-event')"></test>
Wichtig: Verwenden Sie für Ereignisnamen immer Kebab-Groß- / Kleinschreibung. Weitere Informationen und eine Demo zu diesem Punkt finden Sie in der folgenden Antwort: VueJS übergibt den berechneten Wert von der Komponente an die übergeordnete Komponente .
Jetzt müssen wir nur noch dieses ausgegebene benutzerdefinierte Ereignis in der übergeordneten Komponente abhören, wie:
App.vue
<test @my-event="testFunction"></test>
Also, im Grunde anstelle von v-on:click
oder der Abkürzung werden @click
wir einfach v-on:my-event
oder nur verwenden @my-event
.
Demo:
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>
Mit Vue 3
Verwenden von v-bind="$attrs"
:
Vue 3 wird unser Leben in vielerlei Hinsicht viel einfacher machen. Eines der Beispiele dafür ist, dass es uns helfen wird, einen einfacheren transparenten Wrapper mit sehr wenig Konfiguration zu erstellen, indem wir nur verwenden v-bind="$attrs"
. Wenn Sie dies für untergeordnete Komponenten verwenden, funktioniert nicht nur unser Listener direkt vom übergeordneten Element aus, sondern auch jedes andere Attribut funktioniert genauso wie normal <div>
.
In Bezug auf diese Frage müssen wir in Vue 3 nichts aktualisieren, und Ihr Code funktioniert weiterhin einwandfrei, ebenso <div>
wie das Stammelement hier, und er hört automatisch alle untergeordneten Ereignisse ab.
Demo Nr. 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>
Aber für komplexe Komponenten mit verschachtelten Elementen, bei denen wir Attribute und Ereignisse <input />
anstelle der übergeordneten Bezeichnung auf main anwenden müssen, können wir sie einfach verwendenv-bind="$attrs"
Demo # 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>
@click.native="testFunction"