Vuejs 3 和 Bootstrap 5 模态可重用组件以编程方式显示
Vuejs 3 and Bootstrap 5 Modal Reusable Component Show Programmatically
尝试基于 Bootstrap 5,使用 vuejs 3 和可组合 API 创建一个(半)可重用模态组件。设法让它部分工作,
给定(主要是标准 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>
并被
'called'
<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>
我得到了模态 'shown' 但动画淡入淡出不起作用,背景不可见,模态中的数据 bs- 按钮不起作用(即它不会'关闭)。我觉得这与我的整个方法有关。
注意。我不能使用具有 data-bs-toggle="modal" data-bs-target="#exampleModal"
属性的标准按钮,因为该模型的实际触发器来自另一个组件的逻辑(就像设置 bool 一样),并且可重用模式组件将独立于其触发器 ---它也感觉不到正确的 'Vue' 方法。
所以我想我只是 'showing' html,我需要以某种方式实例化一个 bootstrap 模式...只是不知道该怎么做
package.json(以及相关的)
"dependencies": {
"@popperjs/core": "^2.11.2",
"bootstrap": "^5.1.3",
"vue": "^3.2.31",
},
Code sand box here(无法在代码沙箱上获得新的组合 API 和 TS,因此使用标准选项 API 方法稍微重写,所以代码略有不同,但表现出相同的行为)
好的.. 又过了几个小时我想出了一个解决方案,张贴在这里,因为它可能会帮助其他人。
需要创建 bootstrap 模态 'Object'。所以首先必须从 bootstrap 导入模态对象。它的创建需要一个 DOM 引用,因此必须向 html 元素添加一个 ref
,并在脚本中添加一个 ref
道具来保存 link它。
Vue 中的 DOM 引用在安装组件之前不会被填充,因此 Bootstrap 模态对象的构造需要在 Onmounted 中完成,因为 ref
现在 link到实际的 DOM 元素。
然后我没有传递一个 show 道具,因为让父子之间保持同步很麻烦,我只是在对话框组件本身上公开了一个 show
方法(也感觉更优雅)。由于 <script setup>
个对象是 CLOSED BY DEFAULT
, the exposure of the method is done via defineExpose
.. and we now all disco
<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>
和'parent'
<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>
.. 可能还应该添加一个 OnUnmount 来清理对象以保持整洁。
尝试基于 Bootstrap 5,使用 vuejs 3 和可组合 API 创建一个(半)可重用模态组件。设法让它部分工作,
给定(主要是标准 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>
并被
'called'<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>
我得到了模态 'shown' 但动画淡入淡出不起作用,背景不可见,模态中的数据 bs- 按钮不起作用(即它不会'关闭)。我觉得这与我的整个方法有关。
注意。我不能使用具有 data-bs-toggle="modal" data-bs-target="#exampleModal"
属性的标准按钮,因为该模型的实际触发器来自另一个组件的逻辑(就像设置 bool 一样),并且可重用模式组件将独立于其触发器 ---它也感觉不到正确的 'Vue' 方法。
所以我想我只是 'showing' html,我需要以某种方式实例化一个 bootstrap 模式...只是不知道该怎么做
package.json(以及相关的)
"dependencies": {
"@popperjs/core": "^2.11.2",
"bootstrap": "^5.1.3",
"vue": "^3.2.31",
},
Code sand box here(无法在代码沙箱上获得新的组合 API 和 TS,因此使用标准选项 API 方法稍微重写,所以代码略有不同,但表现出相同的行为)
好的.. 又过了几个小时我想出了一个解决方案,张贴在这里,因为它可能会帮助其他人。
需要创建 bootstrap 模态 'Object'。所以首先必须从 bootstrap 导入模态对象。它的创建需要一个 DOM 引用,因此必须向 html 元素添加一个 ref
,并在脚本中添加一个 ref
道具来保存 link它。
Vue 中的 DOM 引用在安装组件之前不会被填充,因此 Bootstrap 模态对象的构造需要在 Onmounted 中完成,因为 ref
现在 link到实际的 DOM 元素。
然后我没有传递一个 show 道具,因为让父子之间保持同步很麻烦,我只是在对话框组件本身上公开了一个 show
方法(也感觉更优雅)。由于 <script setup>
个对象是 CLOSED BY DEFAULT
, the exposure of the method is done via defineExpose
.. and we now all disco
<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>
和'parent'
<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>
.. 可能还应该添加一个 OnUnmount 来清理对象以保持整洁。