Vue3中如何通过JS动态添加组件并监听子组件事件?
Vue3动态添加子组件事件不生效问题
问题描述
学习Vue3过程中需要实现动态添加组件、父组件监听新增子组件事件的功能:预期鼠标移入任意按钮时新增一个按钮,实际只有初始渲染的第一个按钮能触发hello回调,原代码中App.vue里写的"v-on:addButton": hello配置未生效。
问题复现代码
子组件 components/Hello.vue
<script setup lang="ts"> defineProps(['text']) defineEmits(['addButton']) </script> <template> <button @mouseenter="$emit('addButton')">{{ text }}</button> </template>
父组件(问题版本)App.vue
<script setup> import {createApp} from 'vue' import Hello from './components/Hello.vue' let cnt = 0 function hello() { console.log('you enter a button') // 事件绑定写法错误,无法生效 const app = createApp(Hello, {"text": String(cnt++), "v-on:addButton": hello}) const newNode = document.createElement('div') document.getElementById("rootDiv").append(newNode) app.mount(newNode) } </script> <template> <div id="rootDiv"> <Hello text="0" v-on:addButton="hello"/> </div> </template>
修复方案
方案1:修正createApp的事件传参格式
createApp的第二个参数是根组件的入参,事件监听器不能用模板里的v-on:xxx写法,需要按照on+事件名大驼峰的格式传参,把"v-on:addButton": hello改成onAddButton: hello即可正常触发事件。
修改后的hello函数代码:
function hello() { console.log('you enter a button') // 修正事件传参格式 const app = createApp(Hello, { text: String(cnt++), onAddButton: hello }) const newNode = document.createElement('div') document.getElementById("rootDiv").append(newNode) app.mount(newNode) }
方案2:使用数组驱动渲染(官方推荐写法,更简便)
手动调用createApp创建独立实例挂载的方式不符合Vue的响应式设计思路,维护成本高。直接用响应式数组配合v-for循环渲染组件即可,所有子组件的事件会自动绑定,不需要额外处理:
<script setup> import { ref } from 'vue' import Hello from './components/Hello.vue' // 用响应式数组管理所有按钮 const buttonList = ref([{ id: 0 }]) function hello() { console.log('you enter a button') buttonList.value.push({ id: buttonList.value.length }) } </script> <template> <div id="rootDiv"> <Hello v-for="btn in buttonList" :key="btn.id" :text="String(btn.id)" @add-button="hello" /> </div> </template>
内容的提问来源于stack exchange,提问作者Eric Palmer
相关产品推荐
相关产品推荐

