我有两个嵌套组件,从父级访问子方法的正确方法是什么?
this.$children[0].myMethod()
似乎可以解决问题,但它非常丑陋,不是吗,还有什么更好的方法:
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
我有两个嵌套组件,从父级访问子方法的正确方法是什么?
this.$children[0].myMethod()
似乎可以解决问题,但它非常丑陋,不是吗,还有什么更好的方法:
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
您可以使用ref。
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 所示的事件总线。下面是通过将总线作为props传入来使用事件总线的另一个示例。
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/
鉴于所有后代都可以通过 访问根 Vue 实例this.$root
,父组件可以通过this.$children
数组访问子组件,子组件可以通过 访问其父组件this.$parent
,您的第一直觉可能是直接访问这些组件。
VueJS 文档特别出于两个很好的原因警告了这一点:
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 中的组件之间进行通信
建议的解决方案适用于 Vue 2,但如果您最终在这里寻找 Vue 3 Composition API 解决方案,您可以在迁移时执行以下操作:
模板中的子组件,具有方法 "doSomething" :
<div class="form">
<child-component ref="childComponentRef" />
</div>
使用 Vue 2:
this.$refs.childComponentRef.doSomething( );
使用 Vue 3 Composition Api :
setup( )
{
const childComponentRef = ref( );
childComponentRef.value.doSomething( )
return {
childComponentRef
}
}
如果你最终在这里寻找 Vue 3 script setup
<!-- Parent -->
<template>
<ChildComponent ref="childComponentRef" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './components/ChildComponent.vue'
const childComponentRef = ref()
onMounted(() => {
childComponentRef.value.doSomething()
})
</script>
<!-- Child -->
<script setup>
const doSomething = () => {
console.log('Im batman')
}
// Only available in Vue >= 3.1.3
// No need to import
defineExpose({
doSomething
})
</script>
如果您的 Vue 版本是< 3.1.3
,则必须使用setup
function 并返回该doSomething
函数才能在父组件中访问它。
<!-- Child -->
<script>
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
const doSomething = () => {
console.log('Im batman')
}
return { doSomething }
}
})
</script>
当您的控件渲染受v-if
. 所以,我决定采用更简单的方法。
这个想法是使用数组作为队列来发送需要调用到子组件的方法。一旦组件被挂载,它就会处理这个队列。它监视队列以执行新方法。
(从 Desmond Lua 的回答中借用了一些代码)
父组件代码:
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
混合......