Vue父子组件通过ref调用confirmation-dialog时仅弹出父组件弹窗问题求解
问题根因
这个问题的核心是Bootstrap模态框的全局ID冲突,和组件ref没有关联。你当前的confirmation-dialog组件里,所有实例的模态框DOM都硬编码了固定的id="confirmationModalId",触发按钮的data-bs-target也固定写死了#confirmationModalId。HTML规范要求页面ID必须全局唯一,当你同时渲染多个confirmation-dialog实例时,页面会出现多个相同ID的DOM,Bootstrap的data-bs-target只会匹配到页面中第一个出现的对应ID的模态框,也就是你父组件里先渲染的那个,所以不管你调用哪个组件实例的show方法,弹出的都是父组件的弹窗。
解决方案
修改confirmation-dialog组件,给每个实例生成独立的唯一ID,替换所有硬编码的固定ID即可,不需要改动原有父/子组件的调用逻辑,成本最低的修改方式如下:
修改后的组件代码
<template> <!-- Button trigger to Show modal - HIDDEN --> <button ref="hiddenButtonToShowDialog" type="button" class="d-none" data-bs-toggle="modal" :data-bs-target="`#confirmationModal_${_uid}`" > </button> <!-- Modal --> <div class="modal fade" :id="`confirmationModal_${_uid}`" tabindex="-1" :aria-labelledby="`confirmationModalLabel_${_uid}`" aria-hidden="true" > <div class="modal-dialog"> <!-- Button trigger to Hide modal - HIDDEN --> <button ref="hiddenButtonToHideDialog" type="button" class="d-none" data-bs-dismiss="modal" > </button> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" :id="`confirmationModalLabel_${_uid}`" >{{ title }}</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" ></button> </div> <div class="modal-body"> {{ msg }} </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" >{{ cancelBtn }}</button> <button type="button" class="btn btn-primary" @click="clickConfirm" >{{ confirmationBtn }}</button> </div> </div> </div> </div> </template> <script> export default { name: 'ConfirmationDialog', props: { cancelBtn: { type: String, default: 'Cancel' }, confirmationBtn: { type: String, default: 'Confirm' }, title: { type: String, default: 'Confirmation' }, msg: { type: String, default: '' }, }, emits: [ 'show', 'hide', 'confirmed' ], methods: { show () { let btnToShowModal = this.$refs.hiddenButtonToShowDialog btnToShowModal.click() this.$emit('show') }, hide () { let btnToHideModal = this.$refs.hiddenButtonToHideDialog btnToHideModal.click() this.$emit('hide') }, clickConfirm () { this.hide() this.$emit('confirmed') }, } } </script>
这里用到了Vue实例自带的内置属性_uid,它是Vue为每个组件实例自动生成的唯一数字,不需要额外声明或传参,改完组件代码直接生效,每个模态框都会有独立的唯一ID,不会再出现串弹窗的问题。
内容的提问来源于stack exchange,提问作者Gonçalo Bastos
相关产品推荐
相关产品推荐

