Jak wspomniał Chris Fritz (Vue.js Core Team Emeriti ) w VueCONF US 2019
gdybyśmy mieli wejście Kia, .native
a następnie element główny wejścia podstawowego zmienił się z wejścia na etykietę, nagle ten element jest zepsuty i nie jest to oczywiste, a tak naprawdę możesz go nawet nie złapać od razu, chyba że masz naprawdę dobry test. Zamiast tego, unikając używania .native
modyfikatora, który uważam obecnie za anty-wzorzec zostanie usunięty w Vue 3 , będziesz mógł wyraźnie określić, że rodzica może obchodzić, do którego elementu są dodawane słuchacze ...
Dzięki Vue 2
Za pomocą $listeners
:
Tak więc, jeśli używasz Vue 2, lepszym rozwiązaniem tego problemu byłoby użycie w pełni przezroczystej logiki opakowującej . W tym przypadku Vue udostępnia $listeners
właściwość zawierającą obiekt detektorów używanych w komponencie. Na przykład:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
a następnie wystarczy dodać v-on="$listeners"
do test
komponentu:
Test.vue (składnik potomny)
<template>
<div v-on="$listeners">
click here
</div>
</template>
Teraz <test>
komponent jest w pełni przezroczystym opakowaniem , co oznacza, że można go używać dokładnie tak, jak zwykłego <div>
elementu: wszyscy słuchacze będą działać bez .native
modyfikatora.
Próbny:
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>
Za pomocą $emit
metody:
W $emit
tym celu możemy również użyć metody, która pomaga nam słuchać zdarzeń komponentów potomnych w komponencie nadrzędnym. W tym celu musimy najpierw wyemitować zdarzenie niestandardowe z komponentu podrzędnego, takie jak:
Test.vue (składnik potomny)
<test @click="$emit('my-event')"></test>
Ważne: zawsze używaj kebabów w nazwach wydarzeń. Aby uzyskać więcej informacji i demonstrację dotyczącą tego punktu, sprawdź tę odpowiedź: VueJS przekazuje obliczoną wartość z komponentu do rodzica .
Teraz wystarczy odsłuchać emitowane zdarzenie niestandardowe w komponencie nadrzędnym, takie jak:
App.vue
<test @my-event="testFunction"></test>
Tak więc, w zasadzie zamiast v-on:click
skrótu lub po @click
prostu użyjemy v-on:my-event
lub po prostu @my-event
.
Próbny:
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>
Dzięki Vue 3
Używającv-bind="$attrs"
:
Vue 3 znacznie ułatwi nam życie na wiele sposobów. Jednym z przykładów jest to, że pomoże nam to stworzyć prostszą przezroczystą otokę z bardzo mniejszą konfiguracją, po prostu używając v-bind="$attrs"
. Używając tego na komponentach potomnych, nie tylko nasz odbiornik będzie działał bezpośrednio z rodzica, ale także każdy inny atrybut również będzie działał tak jak normalny<div>
.
Tak więc, w odniesieniu do tego pytania, nie będziemy musieli niczego aktualizować w Vue 3, a Twój kod będzie nadal działał dobrze, podobnie jak <div>
tutaj element główny i automatycznie nasłuchuje wszystkich zdarzeń podrzędnych.
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>
Ale w przypadku złożonych komponentów z zagnieżdżonymi elementami, w których musimy zastosować atrybuty i zdarzenia do main <input />
zamiast do etykiety nadrzędnej, możemy po prostu użyćv-bind="$attrs"
Demo nr 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"