У меня есть два вложенных компонента, как правильно получить доступ к дочерним методам от родителя?
this.$children[0].myMethod()
кажется, помогает, но это довольно уродливо, не правда ли, что может быть лучше:
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
javascript
vue.js
al3x
источник
источник
Ответы:
Вы можете использовать исх .
import ChildForm from './components/ChildForm' new Vue({ el: '#app', data: { item: {} }, template: ` <div> <ChildForm :item="item" ref="form" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.$refs.form.submit() } }, components: { ChildForm }, })
Если вам не нравится тесная связь, вы можете использовать шину событий, как показано @Yosvel Quintero. Ниже приведен еще один пример использования шины событий путем передачи шины в качестве опоры.
import ChildForm from './components/ChildForm' new Vue({ el: '#app', data: { item: {}, bus: new Vue(), }, template: ` <div> <ChildForm :item="item" :bus="bus" ref="form" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.bus.$emit('submit') } }, components: { ChildForm }, })
Код компонента.
<template> ... </template> <script> export default { name: 'NowForm', props: ['item', 'bus'], methods: { submit() { ... } }, mounted() { this.bus.$on('submit', this.submit) }, } </script>
https://code.luasoftware.com/tutorials/vuejs/parent-call-child-component-method/
источник
this.$refs.
, вы не должны загружать дочерний компонент динамически.Связь родитель-ребенок в VueJS
Если корневой экземпляр Vue доступен для всех потомков через
this.$root
, родительский компонент может получить доступ к дочерним компонентам черезthis.$children
массив, а дочерний компонент может получить доступ к своему родительскому черезthis.$parent
, ваш первый инстинкт может заключаться в прямом доступе к этим компонентам.Документация VueJS предупреждает об этом по двум очень веским причинам:
Решение - использовать пользовательский интерфейс событий Vue.
Интерфейс событий, реализованный Vue, позволяет вам взаимодействовать вверх и вниз по дереву компонентов. Использование интерфейса настраиваемых событий дает вам доступ к четырем методам:
$on()
- позволяет вам объявить слушателя в вашем экземпляре Vue, с помощью которого вы будете слушать события$emit()
- позволяет запускать события на одном и том же экземпляре (самостоятельно)Пример использования
$on()
и$emit()
:const events = new Vue({}), parentComponent = new Vue({ el: '#parent', ready() { events.$on('eventGreet', () => { this.parentMsg = `I heard the greeting event from Child component ${++this.counter} times..`; }); }, data: { parentMsg: 'I am listening for an event..', counter: 0 } }), childComponent = new Vue({ el: '#child', methods: { greet: function () { events.$emit('eventGreet'); this.childMsg = `I am firing greeting event ${++this.counter} times..`; } }, data: { childMsg: 'I am getting ready to fire an event.', counter: 0 } });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.28/vue.min.js"></script> <div id="parent"> <h2>Parent Component</h2> <p>{{parentMsg}}</p> </div> <div id="child"> <h2>Child Component</h2> <p>{{childMsg}}</p> <button v-on:click="greet">Greet</button> </div>
Ответ взят из исходного сообщения: общение между компонентами в VueJS
источник
Ref и шина событий имеют проблемы, когда на рендеринг элемента управления влияет
v-if
. Итак, я решил пойти по более простому методу.Идея состоит в использовании массива в качестве очереди для отправки методов, которые необходимо вызвать дочернему компоненту. Как только компонент будет смонтирован, он обработает эту очередь. Он наблюдает за очередью, чтобы выполнить новые методы.
(Заимствование кода из ответа Десмонда Луа)
Код родительского компонента:
import ChildComponent from './components/ChildComponent' new Vue({ el: '#app', data: { item: {}, childMethodsQueue: [], }, template: ` <div> <ChildComponent :item="item" :methods-queue="childMethodsQueue" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.childMethodsQueue.push({name: ChildComponent.methods.save.name, params: {}}) } }, components: { ChildComponent }, })
Это код для ChildComponent
<template> ... </template> <script> export default { name: 'ChildComponent', props: { methodsQueue: { type: Array }, }, watch: { methodsQueue: function () { this.processMethodsQueue() }, }, mounted() { this.processMethodsQueue() }, methods: { save() { console.log("Child saved...") }, processMethodsQueue() { if (!this.methodsQueue) return let len = this.methodsQueue.length for (let i = 0; i < len; i++) { let method = this.methodsQueue.shift() this[method.name](method.params) } }, }, } </script>
И есть много возможностей для улучшения, например, переход
processMethodsQueue
на миксин ...источник
Чтобы связать дочерний компонент с другим дочерним компонентом, я создал метод в родительском элементе, который вызывает метод в дочернем элементе с помощью:
this.$refs.childMethod()
А от другого ребенка я вызвал корневой метод:
this.$root.theRootMethod()
У меня это сработало.
источник