Vue.js
Wydarzenia
Szukaj…
Składnia zdarzeń
Aby wysłać zdarzenie: vm.$emit('new-message');
Aby złapać zdarzenie: vm.$on('new-message');
Aby wysłać zdarzenie do wszystkich komponentów w dół : vm.$broadcast('new-message');
Aby wysłać zdarzenie do wszystkich komponentów up: vm.$dispatch('new-message');
Uwaga: $broadcast
i $dispatch
są przestarzałe w Vue2. ( zobacz funkcje Vue2 )
Kiedy powinienem używać wydarzeń?
Poniższy rysunek ilustruje, jak powinna działać komunikacja komponentów. Zdjęcie pochodzi ze slajdów The Progressive Framework autorstwa Evana You (programisty VueJS).
Oto przykład tego, jak to działa:
HTML
<script type="x-template" id="message-box">
<input type="text" v-model="msg" @keyup="$emit('new-message', msg)" />
</script>
<message-box :msg="message" @new-message="updateMessage"></message-box>
<div>You typed: {{message}}</div>
JS
var messageBox = {
template: '#message-box',
props: ['msg']
};
new Vue({
el: 'body',
data: {
message: ''
},
methods: {
updateMessage: function(msg) {
this.message = msg;
}
},
components: {
'message-box': messageBox
}
});
Powyższy przykład można poprawić!
Powyższy przykład pokazuje, jak działa komunikacja komponentowa. Ale w przypadku niestandardowego komponentu wejściowego, aby zsynchronizować zmienną nadrzędną z wpisaną wartością, powinniśmy użyć v-model
.
W Vue1 powinieneś użyć .sync
na .sync
wysłanym do komponentu <message-box>
. To mówi VueJS, aby zsynchronizował wartość w komponencie potomnym z wartością rodzica.
Pamiętaj: każda instancja składnika ma swój własny izolowany zakres.
HTML Vue1
<script type="x-template" id="message-box">
<input v-model="value" />
</script>
<div id="app">
<message-box :value.sync="message"></message-box>
<div>You typed: {{message}}</div>
</div>
W Vue2 istnieje specjalne zdarzenie 'input'
, które możesz $emit
. Użycie tego zdarzenia pozwala umieścić v-model
bezpośrednio na komponencie <message-box>
. Przykład będzie wyglądał następująco:
HTML Vue2
<script type="x-template" id="message-box">
<input :value="value" @input="$emit('input', $event.target.value)" />
</script>
<div id="app">
<message-box v-model="message"></message-box>
<div>You typed: {{message}}</div>
</div>
JS Vue 1 i 2
var messageBox = {
template: '#message-box',
props: ['value']
};
new Vue({
el: '#app',
data: {
message: ''
},
components: {
'message-box': messageBox
}
});
Zauważ, jak szybko aktualizowany jest sygnał wejściowy.
Jak poradzić sobie ze zwolnieniem $ dispatch i $ broadcast? (wzorzec zdarzenia autobusu)
Być może zdałeś sobie sprawę, że zakres $emit
jest ograniczony do komponentu, który emituje zdarzenie. Jest to problem, gdy chcesz komunikować się między komponentami daleko od siebie w drzewie komponentów.
Uwaga: w Vue1 możesz używać $dispatch
lub $broadcast
, ale nie w Vue2. Powodem jest to, że nie skaluje się dobrze. Istnieje popularny schemat zarządzania bus
:
HTML
<script type="x-template" id="sender">
<button @click="bus.$emit('new-event')">Click me to send an event !</button>
</script>
<script type="x-template" id="receiver">
<div>I received {{numberOfEvents}} event{{numberOfEvents == 1 ? '' : 's'}}</div>
</script>
<sender></sender>
<receiver></receiver>
JS
var bus = new Vue();
var senderComponent = {
template: '#sender',
data() {
return {
bus: bus
}
}
};
var receiverComponent = {
template: '#receiver',
data() {
return {
numberOfEvents: 0
}
},
ready() {
var self = this;
bus.$on('new-event', function() {
++self.numberOfEvents;
});
}
};
new Vue({
el: 'body',
components: {
'sender': senderComponent,
'receiver': receiverComponent
}
});
Musisz tylko zrozumieć, że każda instancja Vue()
może $emit
i łapać ( $on
) zdarzenie. Po prostu deklarujemy globalną bus
wywołań instancji Vue
a następnie dowolny komponent z tą zmienną może emitować i wychwytywać z niej zdarzenia. Upewnij się tylko, że komponent ma dostęp do zmiennej bus
.