You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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实现事件总线:

  1. 安装mitt:npm install mitt
  2. 创建事件总线文件bus.js:
import mitt from 'mitt'
const emitter = mitt()
export default emitter
  1. 在formComponent中监听事件:
import emitter from './bus.js'

export default {
  // ...其他代码
  mounted() {
    console.log('form mounted');
    emitter.on('displayForm', () => {
      this.displayForm();
    });
  },
  beforeUnmount() {
    // 组件销毁时移除监听,避免内存泄漏
    emitter.off('displayForm');
  }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:15:37