Vue3中如何跨组件调用函数?尝试$on等方法出现报错
跨组件调用方法的正确实现方案
需求:从CommonComponent组件调用formComponent组件的displayForm()方法,此前尝试$on及this.$root.$refs.compname_component = this的方式均报错,相关代码如下:
原组件代码
formComponent.vue
<template> <div v-if="showForm"> create Form </div> </template> <script> export default { props:[], setup(props) { return props; }, data() { return { formData:{}, showForm:false } }, created() { // this.$root.$refs.tableCommon = this; // this.$root.$refs.compname_component = this; }, mounted() { console.log('form mounted'); // this.$root.$on("displayForm", () => { // this.displayForm(); // }); }, methods: { displayForm:function(){ this.showForm = true; } }, } </script>
commonComponent.vue
<template> <div class="col-10 text-end custom-inline-spacing mb-3"> <button type="button" class="btn btn-outline-secondary" @click="showCreateForm">Create</button> </div> </template> <script> export default { props: [], setup() { return {} }, data() { return {} }, mounted() { console.log('mounted common') }, methods: { showCreateForm : function(){ // this.$refs.form.displayForm(); // this.$root.$refs.compname_component.displayForm(); // this.$root.$emit("displayForm"); this.createForm.displayForm(); } } } </script>
app.js
require('./bootstrap') import { createApp } from 'vue' import tableCommon from './components/CommonComponent' import createForm from './components/formComponent'; const app = createApp({}) app.component('vue-common', tableCommon); app.component('create-form', createForm); app.mount('#app')
正确实现方法
方法1:父组件中转(符合Vue单向数据流规范)
Vue推荐通过父组件作为中间层传递状态或触发事件,避免直接跨组件调用。
修改后的代码:
App.vue(父组件)
<template> <div id="app"> <vue-common @show-form="handleShowForm"></vue-common> <create-form ref="formRef"></create-form> </div> </template> <script> export default { methods: { handleShowForm() { // 调用formComponent的displayForm方法 this.$refs.formRef.displayForm(); } } } </script>
commonComponent.vue(触发事件)
methods: { showCreateForm : function(){ // 向父组件触发事件 this.$emit('show-form'); } }
方法2:使用全局事件总线(Vue 3适配版)
Vue 3移除了$on/$off,可以用第三方库mitt实现事件总线:
- 安装
mitt:npm install mitt - 创建事件总线文件
bus.js:
import mitt from 'mitt' const emitter = mitt() export default emitter
- 在
formComponent中监听事件:
import emitter from './bus.js' export default { // ...其他代码 mounted() { console.log('form mounted'); emitter.on('displayForm', () => { this.displayForm(); }); }, beforeUnmount() { // 组件销毁时移除监听,避免内存泄漏 emitter.off('displayForm'); } }
- 在
commonComponent中触发事件:
import emitter from './bus.js' export default { // ...其他代码 methods: { showCreateForm : function(){ emitter.emit('displayForm'); } } }
方法3:直接通过ref获取组件实例(仅限同层级父组件下)
如果两个组件在同一个父组件内,可以通过父组件的ref直接调用:
父组件(App.vue):
<template> <vue-common @click="showCreateForm"></vue-common> <create-form ref="createFormRef"></create-form> </template> <script> export default { methods: { showCreateForm() { this.$refs.createFormRef.displayForm(); } } } </script>
内容的提问来源于stack exchange,提问作者noushid p
相关产品推荐
相关产品推荐

