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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 17:36:01