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
相关产品推荐
相关产品推荐

