ModelessDialog 非模态对话框
基于Panel构建的非模态对话框,支持最大化,最小化,收起,展开,拖拽改变大小等功能,常用于预览文件,视频,音频等常驻页面操作。
基础用法
可以通过声明组件的形式,实例化该组件。在点击关闭或者路由切换以后,该组件自动销毁
可以在style中设置left/top覆盖默认的弹出位置
vue
<template>
<el-button @click="show">{{ visible ? 'Hide' : 'Show' }}</el-button>
<epp-modeless-dialog v-model="visible" title="非模态对话框示例" resize @resize="resizeCB">
<p>非模态对话框示例</p>
</epp-modeless-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const visible = ref(false);
const show = () => {
visible.value = !visible.value;
};
const resizeCB = () => {
console.log('resizing...');
};
</script>
拖动范围
可以通过 boundings
属性限定可拖拽范围,boundings
为四个数值的数组,分别为左上角坐标(x,y)与右下角坐标(x,y)
范围:左上角(0,0) / 右下角(1000,600)
Range: Top-left (0, 0) / Bottom-right (1000, 600)
示例代码
vue
<template>
<el-button @click="show">{{ visible ? 'Hide' : 'Show' }}</el-button>
<div class="m-t-md">范围:左上角(0,0) / 右下角(1000,600)</div>
<div class="m-t-md">Range: Top-left (0, 0) / Bottom-right (1000, 600)</div>
<epp-modeless-dialog v-model="visible" width="400px" title="非模态对话框示例" :boundings="[0, 0, 1000, 600]">
<p>非模态对话框示例</p>
</epp-modeless-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const visible = ref(false);
const show = () => {
visible.value = !visible.value;
};
</script>
使用ModelessDialogManager
通过调用 ModelessDialogManager
API的 show
方法创建对话框,此对话框可以在页面切换以后保持不被销毁。
id
属性需要唯一固定值
vue
<template>
<el-space size="large">
<el-button @click="create">创建(Create)</el-button>
<el-button @click="close">手动关闭(Close Manually)</el-button>
</el-space>
</template>
<script lang="ts" setup>
import { h } from 'vue';
import { ElEmpty } from 'element-plus';
import { ModelessDialogManager } from 'element-plus-plus';
const close = () => {
ModelessDialogManager.get('my-modelesss-dialog').close();
};
const create = () => {
ModelessDialogManager.show({
id: 'my-modelesss-dialog',
title: '测试Manager',
body: h(ElEmpty, { description: '空内容' }),
resize: true,
onResize: (dlg: HTMLDivElement) => {
console.log('resize', dlg);
},
onOpen: () => {
console.log('open');
},
onOpened: () => {
console.log('opened');
},
onClose: () => {
console.log('close');
},
onClosed: () => {
console.log('closed');
},
onDestroy: () => {
console.log('destroy');
},
onCollapse: (value: boolean) => {
console.log('collapse', value);
},
onMaximize: (value: boolean) => {
console.log('maximize', value);
},
});
};
</script>
ModelessDialogManager API示例
状态(Status):隐藏(Hide)
header
,body
,footer
必须为VNode实例,否则不进行处理
vue
<template>
<el-space size="large">
<el-button @click="create">创建(Create)</el-button>
<el-tag>状态(Status):{{ visible ? '显示(Show)' : '隐藏(Hide)' }}</el-tag>
</el-space>
<br /><br />
<el-space size="large">
<el-button @click="max">最大化(Max)</el-button>
<el-button @click="collapse">折叠(Collapse)</el-button>
<el-button @click="show">显示/隐藏(Show/Hide)</el-button>
<el-button @click="close">手工关闭(Close Manually)</el-button>
</el-space>
<hr />
<el-space size="large" class="m-t-lg">
<el-button @click="create2">创建多个对话框(Create Dialogs)</el-button>
</el-space>
<br />
<el-space size="large" class="m-t-lg">
<el-button @click="collaseAll">折叠所有(Collapse All)</el-button>
<el-button @click="closeAll">关闭所有(Close All)</el-button>
<el-button @click="hideAll">隐藏所有(Hide All)</el-button>
<el-button @click="showAll">显示所有(Show All)</el-button>
</el-space>
</template>
<script lang="ts" setup>
import { ref, h } from 'vue';
import { ElButton } from 'element-plus';
import { ModelessDialogManager } from 'element-plus-plus';
const inputVal = ref('');
const visible = ref(false);
const create = () => {
ModelessDialogManager.show({
id: 'my-modelesss-dialog2',
title: '测试Manager,固定ID',
body: h('input', {
value: inputVal.value,
style: 'border: 1px solid #efefef',
onInput: (e: InputEvent) => {
inputVal.value = (e.target as HTMLInputElement).value;
},
}),
footer: h('div', null, [
h(ElButton, { type: 'primary', class: 'm-r-md' }, { default: () => '确定' }),
h(ElButton, null, { default: () => '取消' }),
]),
});
visible.value = ModelessDialogManager.get('my-modelesss-dialog2').isShown();
};
const show = () => {
ModelessDialogManager.get('my-modelesss-dialog2').toggleShow();
visible.value = ModelessDialogManager.get('my-modelesss-dialog2').isShown();
};
const max = () => {
ModelessDialogManager.get('my-modelesss-dialog2').toggleMaximize();
};
const collapse = () => {
ModelessDialogManager.get('my-modelesss-dialog2').toggleCollapse();
};
const close = () => {
ModelessDialogManager.get('my-modelesss-dialog2').close();
};
const create2 = () => {
ModelessDialogManager.show({
title: '测试Manager',
});
};
const collaseAll = () => {
ModelessDialogManager.collapseAll();
};
const closeAll = () => {
ModelessDialogManager.closeAll();
};
const showAll = () => {
ModelessDialogManager.showAll();
};
const hideAll = () => {
ModelessDialogManager.hideAll();
};
</script>
ModelessDialogManager API响应式示例
如果需要动态修改对话框,可以使用 reactive
包装所有属性。
示例代码
vue
<template>
<el-space size="large">
<el-button @click="create">创建(Create)</el-button>
<el-button @click="modifyProp">修改对话框属性(Modify properties)</el-button>
</el-space>
<br /><br />
<el-space size="large">
<el-button @click="modifySlot">修改Slot(Modify slot)</el-button>
<el-button @click="modifyPanel">修改Panel属性(Modify panel properties)</el-button>
</el-space>
</template>
<script lang="ts" setup>
import { ref, reactive, h } from 'vue';
import { ElButton } from 'element-plus';
import { ModelessDialogManager } from 'element-plus-plus';
const inputVal = ref('');
const dialogProps = reactive({
id: 'my-modelesss-dialog3',
borderless: true,
bodyPadding: 'var(--lg)',
title: '测试Manager',
body: h('input', {
value: inputVal.value,
onInput: (e: InputEvent) => {
inputVal.value = (e.target as HTMLInputElement).value;
},
}),
footer: h('div', null, [
h(ElButton, { type: 'primary', class: 'm-r-md' }, { default: () => '确定' }),
h(ElButton, null, { default: () => '取消' }),
]),
});
const create = () => {
ModelessDialogManager.show(dialogProps);
};
const modifyProp = () => {
dialogProps.title = '修改对话框标题';
};
const modifySlot = () => {
dialogProps.footer = h('div', { innerHTML: '修改Footer Slot内容' });
};
const modifyPanel = () => {
dialogProps.borderless = false;
dialogProps.bodyPadding = '8px';
};
</script>
图片/视频/文档预览示例
- 可以拖拽右下角改变大小
- 可以最大化,最小化
- 可以切换路由,保持浮窗不关闭
示例代码
vue
<template>
<el-space size="large">
<el-button @click="create1">图片(Image)</el-button>
<el-button @click="create2">多张图(2x2 Image)</el-button>
<el-button @click="create3">PDF预览(Preview)</el-button>
</el-space>
</template>
<script lang="ts" setup>
import { h } from 'vue';
import { withBase } from 'vitepress';
import { ModelessDialogManager } from 'element-plus-plus';
const create1 = () => {
ModelessDialogManager.show({
customClass: 'example-modeless',
title: '图片预览',
width: '40vw',
height: '30vh',
body: h('div', { class: 'image-example', innerHTML: `<img src="${withBase('/zen.jpg')}" />` }),
resize: true,
onResize: (dlg: HTMLDivElement) => {
console.log('resize', dlg);
},
});
};
const create2 = () => {
ModelessDialogManager.show({
customClass: 'example-modeless2',
title: '图片预览',
width: '40vw',
height: '30vh',
body: h('div', {
class: 'image-example2',
innerHTML: `
<img src="${withBase('/zen.jpg')}" />
<img src="${withBase('/zen.jpg')}" />
<img src="${withBase('/zen.jpg')}" />
<img src="${withBase('/zen.jpg')}" />
`,
}),
resize: true,
onResize: (dlg: HTMLDivElement) => {
console.log('resize', dlg);
},
});
};
const create3 = () => {
ModelessDialogManager.show({
customClass: 'example-modeless3',
title: 'PDF预览',
width: '40vw',
height: '50vh',
body: h('iframe', { class: 'pdf-example', src: `${withBase('/example.pdf')}` }),
resize: true,
});
};
</script>
<style lang="scss">
.example-modeless,
.example-modeless2 {
.panel-body {
height: calc(100% - var(--panel-header-height));
}
}
.example-modeless3 {
.panel-body {
padding: 0;
height: calc(100% - var(--panel-header-height));
}
}
.image-example {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.image-example2 {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
gap: 10px;
img {
width: calc(50% - 20px / 2);
height: calc(50% - 20px / 2);
object-fit: cover;
}
}
.pdf-example {
width: 100%;
height: 100%;
}
</style>
配合DockContainer使用
请参见DockContainer组件文档。
Attributes
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
model-value / v-model | 是否显示对话框 | boolean | — | — |
width | 对话框的宽度 | string | — | - |
height | 对话框的高度 | string | — | - |
top | 对话框 CSS 中的 top 值 | string | — | - |
resize | 右下角是否可拖拽改变大小 | boolean | — | false |
drag | 是否可拖拽 | boolean | — | true |
boundings | 可拖拽范围 | array | — | - |
custom-class | 对话框的自定义类名 | string | — | — |
open-delay | 对话框打开的延时时间,单位毫秒 | number | — | 0 |
close-delay | 对话框关闭的延时时间,单位毫秒 | number | — | 0 |
show-close | 是否显示关闭按钮 | boolean | — | true |
show-maximize | 是否显示最大化按钮 | boolean | — | true |
show-collapse | 是否显示折叠按钮 | boolean | — | true |
before-close | 关闭前的回调,会暂停对话框的关闭 | function(done),done 用于关闭 Dialog | — | — |
animation-name | 对话框动画类型 | string | - | - |
title | 对话框标题,优先级低于header slot | string | - | - |
z-index | 自定义层级 | number | - | - |
id | 对话框根节点id | string | - | - |
use-dock | 是否配合DockContainer使用。如果设置为true,折叠时会把对话框收纳到DockContainer中去 | boolean | - | false |
snapshot | 配合DockContainer使用时,需要展示的形式 | boolean / string / object { type: string, url: string } | - | false |
Panel组件属性 | 对话框基于Panel组件构建,自动支持使用Panel组件所有属性 | - | - | - |
Slots
名称 | 说明 |
---|---|
default | 自定义内容 |
header | 自定义头部 |
footer | 自定义底部 |
Events
事件名称 | 说明 | 回调参数 |
---|---|---|
open | 对话框打开的回调 | — |
opened | 对话框打开动画结束时的回调 | — |
close | 对话框关闭的回调 | — |
closed | 对话框关闭动画结束时的回调 | — |
resize | 对话框拖拽改变大小回调 | 对话框DOM根节点 |
maximize | 对话框最大化/最小化回调 | 是否最大化 |
collapse | 对话框收起/展开回调 | 是否收起 |
ModelessDialogManager Methods
方法名 | 说明 | 参数 |
---|---|---|
show | 显示对话框,会自定检查指定id的对话框是否存在,如果存在将直接返回已存在对话框实例 | 对话框所支持属性 & { header: VNode, body: VNode, footer: VNode } |
get | 获取对话框实例 | 对话框id |
has | 检查对话框是否已经存在 | 对话框id |
closeAll | 关闭所有对话框 | - |
showAll | 显示所有对话框 | - |
hideAll | 隐藏所有对话框 | - |
collapseAll | 折叠多有对话框 | - |
expandAll | 展开所有对话框 | - |
ModelessDialog Instance Methods
方法名 | 说明 | 参数 |
---|---|---|
close | 关闭对话框 | - |
toggleShow | 显示/隐藏对话框 | shown: boolean,手动设置显示或者隐藏 |
toggleCollapse | 折叠/展开对话框 | collapsable: boolean,手动设置折叠或者展开 |
toggleMaximize | 最大化/还原对话框 | maximizable: boolean,手动设置最大化 |
isShown | 对话框已经显示 | - |
isClosed | 对话框是否已经关闭 | - |
isCollapsed | 对话框是否已经折叠 | - |
isMaximized | 对话框是否已经最大化 | - |