Связь между двумя компонентами (не связана с дочерним родителем)
компонент 1
getMyProfile(){
this.$root.$emit('event');
console.log("emited")
},
компонент 2
mounted() {
this.$root.$on('event', () = {
alert("Fired");
}
}
Я пытаюсь предупредить "выстрел" из компонента 2 из компонента 1. Но этого не происходит. что я делаю не так Должен ли я добавить что-то на основной JS?
4 ответа
Кроме маленькой опечатки в вашем $on
непонятно, что вы делаете неправильно, поскольку вы не предоставили достаточно контекста, но вот рабочий пример того, что именно вы пытаетесь сделать (отправка и получение события через $root
элемент, без создания отдельного экземпляра EventUue Vue). (Многие люди предпочитают передавать сообщения через отдельный экземпляр, но это функционально похоже на $root
.)
Я включил объект полезной нагрузки, чтобы продемонстрировать передачу информации вместе с событием.
Vue.component('sender', {
template: '<span><button @click="send">Sender</button></span>',
methods: {
send() {
console.log("Sending...")
this.$root.$emit('eventName', {
message: "This is a message object sent with the event"
})
}
}
})
Vue.component('receiver', {
template: '<span>Receiver component {{message}}</span>',
data() {return {message: ''}},
mounted() {
this.$root.$on('eventName', (payload) => {
console.log("Received message", payload)
this.message = payload.message
})
}
})
new Vue({
el: '#app'
});
<script src="https://unpkg.com/vue@latest/dist/vue.min.js"></script>
<div id="app">
<sender></sender>
<receiver></receiver>
</div>
Лично я не склонен часто использовать этот шаблон; Я считаю, что лучше обрабатывать межкомпонентную связь от родителя к потомку как реквизит, а от потомка к родителю как прямой $emit
с (не включен $root
). Когда я обнаруживаю, что мне нужно общение между братьями и сестрами, это, как правило, признак того, что я сделал несколько неудачных архитектурных решений или что мое приложение стало достаточно большим, чтобы я мог переключиться на vuex. Сбор всех сообщений о событиях в одном месте, будь то $root
или экземпляр Eventbus, как правило, усложняет анализ приложения и отладку.
По крайней мере, вы должны очень четко обозначать свои события, чтобы легче было понять, откуда они берутся; имена событий, такие как "handleClick" или просто "event", быстро становятся загадочными неизвестными.
Итак, что вы ищете, так это шину событий (глобальные события)
Я бы посоветовал рассмотреть возможность использования vuex в любое время, когда вам нужно реализовать шину событий.
Давайте вернемся к проблеме.
Создать файл event-bus.js
это то, что будет собирать и распространять события.
import Vue from 'vue'
const EventBus = new Vue()
export default EventBus
Теперь в вашем main.js
зарегистрировать свой автобус
import Vue from 'vue'
import eventBus from './event-bus'
//other imports
Vue.prototype.$eventBus = eventBus
new Vue({
...
}).$mount('#app')
Теперь вы можете:
- слушать события с
this.$eventBus.$on(eventName)
- испускать события
this.$eventBus.$emit(eventName)
В этом примере я перенесу событие из дочернего в родительский компонент с $emit
Дочерний компонент:
Vue.component('Child component ', {
methods: {
getMyProfile: function() {
this.$emit('me-event', 'YUP!')
}
},
template: `
<button v-on:click="getMyProfile">
Emmit Event to Parrent
</button>
`
})
Родительский компонент:
Vue.component('Parent component ', {
methods: {
getEventFromChild: function(event) {
alert(event)
}
}
template: `
<div>
<Child-component v-on:me-event="getEventFromChild" />
</div>
`
})
например, когда у вас есть поток данных в одну сторону от родителя к потомку, и вы хотите перенести данные от потомка к родителю, вы можете использовать $emit и перенести их от потомка... а в родителе вы должны перехватить его с помощью директивы v-on. (простите мой английский)
Если компонент 2 является родителем компонента 1, вы можете сделать:
getMyProfile(){
this.$emit('myevent');
console.log("emited")
},
для компонента 2
<componant-2 @myevent="dosomething" ...></componant-2>
и во втором компоненте
methods: {
dosomething() {
console.log('Event Received');
}
}