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

Vue3 Options API动态组件的v-on/@事件绑定问题

解决Vue3 Options API动态组件事件绑定问题

方法一:统一子组件事件名(推荐)

如果可以修改子组件,建议给所有子组件统一触发的事件名(比如switch-page),子组件点击按钮时传递目标组件名称,父组件只用一个处理函数就能完成页面切换,逻辑更简洁。

子组件修改示例(以ComponentA为例)

<!-- componentA.vue -->
<template>
  <button @click="$emit('switch-page', 'componentB')">{{ label }}</button>
</template>
<script>
export default {
  props: ['label']
}
</script>

ComponentB、ComponentC同理,点击时分别传递componentC、componentA即可。

父组件修改

<!-- app.vue -->
<template>
  <component :is="currentPage" v-bind="currentProps" @switch-page="handleSwitchPage"></component>
</template>

<script>
import componentA from '~/components/componentA.vue'
import componentB from '~/components/componentB.vue'
import componentC from '~/components/componentC.vue'

export default {
  components: {
    componentA,
    componentB,
    componentC,
  },
  data() {
    return { 
      currentPage: 'componentA',
      // 维护组件与对应props的映射表
      pageConfig: {
        componentA: { label: 'go to B' },
        componentB: { label: 'go to C' },
        componentC: { label: 'go to A' }
      }
    }
  },
  methods: {
    handleSwitchPage(targetPage) {
      this.currentPage = targetPage
      this.currentProps = this.pageConfig[targetPage]
    }
  }
}
</script>

方法二:动态绑定事件对象(适配原有事件名)

如果不想修改子组件的原有事件名,可以在父组件中维护一个currentEvents对象,切换页面时同步更新对应的事件绑定,再通过v-on="currentEvents"绑定到动态组件上。

父组件修改(基础版)

<!-- app.vue -->
<template>
  <component :is="currentPage" v-bind="currentProps" v-on="currentEvents"></component>
</template>

<script>
import componentA from '~/components/componentA.vue'
import componentB from '~/components/componentB.vue'
import componentC from '~/components/componentC.vue'

export default {
  components: {
    componentA,
    componentB,
    componentC,
  },
  data() {
    return { 
      currentPage: 'componentA',
      currentProps: { label: 'go to B' },
      currentEvents: { 'event-of-a': this.goToB }
    }
  },
  methods: {
    goToA(){
      this.currentPage = 'componentA'
      this.currentProps = { label: 'go to B' }
      this.currentEvents = { 'event-of-a': this.goToB }
    },
    goToB(){
      this.currentPage = 'componentB'
      this.currentProps = { label: 'go to C' }
      this.currentEvents = { 'event-of-b': this.goToC }
    },
    goToC(){
      this.currentPage = 'componentC'
      this.currentProps = { label: 'go to A' }
      this.currentEvents = { 'event-of-c': this.goToA }
    }
  }
}
</script>

优化版(整合配置,减少重复代码)

可以把每个页面的props和事件映射整合到一个配置表中,通过计算属性动态获取当前值:

<script>
// ... 导入组件代码不变
export default {
  components: { componentA, componentB, componentC },
  data() {
    return { 
      currentPage: 'componentA',
      pageConfigs: {
        componentA: {
          props: { label: 'go to B' },
          events: { 'event-of-a': this.goToB }
        },
        componentB: {
          props: { label: 'go to C' },
          events: { 'event-of-b': this.goToC }
        },
        componentC: {
          props: { label: 'go to A' },
          events: { 'event-of-c': this.goToA }
        }
      }
    }
  },
  computed: {
    currentProps() {
      return this.pageConfigs[this.currentPage].props
    },
    currentEvents() {
      return this.pageConfigs[this.currentPage].events
    }
  },
  methods: {
    goToA(){ this.currentPage = 'componentA' },
    goToB(){ this.currentPage = 'componentB' },
    goToC(){ this.currentPage = 'componentC' }
  }
}
</script>

内容的提问来源于stack exchange,提问作者Anna Jsk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:50:22