Vuejs 3 和 Bootstrap 5 模态可重用组件以编程方式显示

OJa*_*Jay 13 typescript vue-component vuejs3 bootstrap-5

尝试使用 vuejs 3 和可组合 API 创建一个基于 Bootstrap 5 的(半)可重用模态组件。设法让它部分工作,
给定(主要是标准 Bootstrap 5 模式,但基于“show”属性添加类,以及正文和页脚中的插槽):

<script setup lang="ts">
defineProps({
  show: {
    type: Boolean,
    default: false,
  },
  title: {
    type: String,
    default: "<<Title goes here>>",
  },
});
</script>

<template>
  <div class="modal fade" :class="{ show: show, 'd-block': show }"
    id="exampleModal" tabindex="-1" aria-labelledby="" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">{{ title }}</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <slot name="body" />
        </div>
        <div class="modal-footer">
          <slot name="footer" />
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
            Close
          </button>              
        </div>
      </div>
    </div>
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

并被“召唤”

<script setup lang="ts">
import { ref } from "vue";
import Modal from "@/components/Common/Modal.vue";

let modalVisible= ref(false);

function showModal(){
 modalVisible.value = true;
}
</script>

<template>
  <button @click="showModal">Show Modal</button>
  <Modal title="Model title goes here" :show="modalVisible">
    <template #body>This should be in the body</template>
    <template #footer>
      <button class="btn btn-primary">Extra footer button</button>
    </template>
</Modal>
</template>
Run Code Online (Sandbox Code Playgroud)

我得到一个模式“显示”,但动画淡入淡出不起作用,背景不可见,并且模式中的数据按钮不起作用(即它不会关闭)。我觉得这与我的整个方法有关。

在此输入图像描述

笔记。我无法使用带有属性的标准按钮data-bs-toggle="modal" data-bs-target="#exampleModal",因为该模型的实际触发器来自另一个组件的逻辑(如仅设置布尔值),并且可重用的模式组件将独立于其触发器——它也不会感受正确的“Vue”方式来做到这一点。

所以我认为我只是“显示”html,并且我需要以某种方式实例化引导模式......只是不知道该怎么做

package.json(以及相关的)

"dependencies": {
    "@popperjs/core": "^2.11.2",
    "bootstrap": "^5.1.3",
    "vue": "^3.2.31",
  },
Run Code Online (Sandbox Code Playgroud)

此处的代码沙箱(无法在代码沙箱上使用新的组合 API 和 TS,因此它使用标准选项 API 方法进行了轻微的重写,因此代码略有不同,但表现出相同的行为)

OJa*_*Jay 23

好吧..又过了几个小时,我想出了一个解决方案,在这里发布,因为它可能会帮助其他人。需要创建引导模式“对象”。因此首先必须从引导程序导入模式对象。它的创建需要一个 DOM 引用,因此必须添加一个ref到 html 元素,并ref在脚本中添加一个 prop 来保存指向它的链接。Vue 中的 DOM 引用在组件安装后才会填充,因此 Bootstrap 模式对象的构造需要在 Onmounted 中完成,因为ref现在将链接到实际的 DOM 元素。然后,我没有向下传递 show prop,因为使父子之间保持同步很麻烦,而是show在对话框组件本身上公开了一个方法(也感觉更优雅)。由于<script setup>对象是CLOSED BY DEFAULT,该方法的暴露是通过defineExpose..完成的,我们现在都迪斯科

<script setup lang="ts">
import { onMounted, ref } from "vue";
import { Modal } from "bootstrap";
defineProps({
  title: {
    type: String,
    default: "<<Title goes here>>",
  },
});
let modalEle = ref(null);
let thisModalObj = null;

onMounted(() => {
  thisModalObj = new Modal(modalEle.value);
});
function _show() {
  thisModalObj.show();
}
defineExpose({ show: _show });
</script>

<template>
  <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby=""
    aria-hidden="true" ref="modalEle">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">{{ title }}</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <slot name="body" />
        </div>
        <div class="modal-footer">
          <slot name="footer"></slot>
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
            Close
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

和“父母”

<script setup lang="ts">
import { ref } from "vue";
import Modal from "@/components/Common/Modal.vue";

let thisModal= ref(null);

function showModal(){
 thisModal.value.show();
}
</script>

<template>
  <button @click="showModal">Show Modal</button>
  <Modal title="Model title goes here" ref="thisModal">
    <template #body>This should be in the body</template>
    <template #footer>
      <button class="btn btn-primary">Extra footer button</button>
    </template>
</Modal>
</template>
Run Code Online (Sandbox Code Playgroud)

..也许还应该添加一个OnUnmount来清理对象以使其整洁。