安装与调用
如果是基本弹框功能,直接引用下面CSS和JS即可:
<link rel="stylesheet" href="https://unpkg.com/lu2/theme/edge/css/common/ui/Button.css"> <link rel="stylesheet" href="https://unpkg.com/lu2/theme/edge/css/common/ui/Dialog.css">
<script type="module" src="https://unpkg.com/lu2/theme/edge/js/common/ui/Dialog.js"></script>
或者:
<script type="module">
import Dialog from "https://unpkg.com/lu2/theme/edge/js/common/ui/Dialog.js";
</script>
如果需要用到loading弹框,则还需要引入Loading.css,如下:
<link rel="stylesheet" href="https://unpkg.com/lu2/theme/edge/css/common/ui/Loading.css">
如果是npm安装调用,则:
import 'lu2/theme/edge/css/common/ui/Button.css'; import 'lu2/theme/edge/css/common/ui/Dialog.css'; // 可选 import 'lu2/theme/edge/css/common/ui/Loading.css'; import 'lu2/theme/edge/js/common/ui/Dialog.js';
如果 JS import语法报错,试试在业务代码中动态引入。
import('lu2/theme/edge/js/common/ui/Dialog.js');
概要
Edge主题中的Dialog组件性质上已经变成DOM组件,有别于peak、pure主题中原型组件。大家可以理解为对HTML5原生的<dialog>元素进行的扩展。
目前Firefox浏览器和Safari浏览器并不支持<dialog>元素,本组件进行了简易的Ployfill,可以满足常规的弹框需求。
本Dialog组件的所有功能都是围绕<dialog>元素的属性和方法展开的,使用的时候需要给<dialog>元素添加is="ui-dialog",否则还是原始UI的<dialog>元素。
例如:
<dialog id="dialog" is="ui-dialog"></dialog>
此时,设置该<dialog>元素的open属性值为true,就可以显示弹框。
测试:
button.addEventListener('click', function () {
dialog.open = true;
});
支持使用data-params传递各类通用参数,例如:
<dialog is="ui-dialog" data-params="{
title: '我是标题',
closable: false,
onHide: function () {
console.log('隐藏了~');
},
buttons: [{}, {}]
}">我是内容</dialog>
测试:
之前<dialog>内置内容会自动放在div.ui-dialog-body元素中,不过这会影响Vue/React等框架的渲染,因此,再2024之后的版本,不会对<dialog>中的元素进行任何DOM层级这块的调整,大家需要需要合理的间距,可以自行在外面包裹div.ui-dialog-body元素。
弹框的显示、隐藏
弹框显示有3种方法,分别是:
- dialog.open = true;
- dialog.setAttribute('open', '');
- dialog.show();
- dialog.showModal(); // 推荐
其中showModal()方法是模态显示,层级顶级,覆盖元素无法被点击。如果希望其他的显示方法也采用模态显示,可以添加modal属性。
<dialog modal is="ui-dialog"></dialog>
例如,点击下面按钮,设置某<dialog>元素的open为true,看看是不是模态对话框?
弹框隐藏有4种方法,分别是:
- dialog.open = false;
- dialog.removeAttribute('open');
- dialog.close();
- dialog.hide(); // 非原生方法
显示和隐藏测试
弹框的创建
实际开发,弹框往往并不是在页面中的,需要JS创建,此时按照普通的DOM元素创建使用就可以了。
这里列举3个不同的弹框创建案例:
1. DOM创建
测试:
点击按钮执行的代码如下:
let dialog = document.createElement('dialog');
dialog.setAttribute('is', 'ui-dialog');
dialog.addEventListener('DOMContentLoaded', function () {
this.alert('Hello, LuLu UI!');
});
document.body.appendChild(dialog);
2. HTML字符串
测试:
点击按钮执行的代码如下:
document.body.insertAdjacentHTML('beforeend', '<dialog id="dialogAlert" is="ui-dialog"></dialog>');
dialogAlert.addEventListener('DOMContentLoaded', function () {
this.alert('Hello, LuLu UI!');
});
3. Dialog类创建
测试:
点击按钮执行的代码如下:
new Dialog().alert('Hello, LuLu UI!');
Dialog对象隐藏了创建的细节,是更推荐的元素创建方法,详见“Dialog类使用指南”。
弹框的删除
弹框删除可以使用下面的方法:
- dialog.remove();
测试:
比方说下面这个例子:
new Dialog({
content: '<button onclick="this.closest(\'dialog\').remove()">删除弹框</button>'
});
如果弹框内容以字符串形式设置,则弹框关闭默认执行的就是删除操作,而不是隐藏。
弹框内容设置
如果需要让弹框显示对应的内容,则有下面这些方法:
1. 直接显示
需要显示的内容内容直接放在<dialog>元素中,例如:
<dialog id="dialog2" is="ui-dialog" title="我是标题">
下拉:<select is="ui-select" style="width: 150px">
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
</select>
</dialog>
此时弹框直接显示已有内容,例如:
dialog2.show();
测试:
其中,<dialog>元素上的title属性值会作为弹框的标题显示。此title属性是一次性的,也就是后期再使用dialog.title修改title属性是无效的,请使用dialog.params.title进行标题的修改。
2. params参数传递
本弹框组件的参数传递底层使用的是dialog.params对象,因此,对于弹框内容,就可以通过dialog.params.content。例如:
<dialog id="dialog3" is="ui-dialog"></dialog>
dialog3.params.content = 'Hello, LuLu UI!'; dialog3.show();
如果希望弹框关闭后还能继续显示当前弹框,需要使用节点对象作为弹框内容。例如本例中需要把文字转为文本节点使用:
button3.addEventListener('click', function () {
dialog3.params.content = document.createTextNode('Hello, LuLu UI!');
dialog3.show();
});
测试:
3. 直接在<dialog>元素上设置
<dialog>元素扩展了一个可读写的content属性,可以用来直接改变弹框内容。
<dialog id="dialog3" is="ui-dialog"></dialog>
button4.addEventListener('click', function () {
dialog4.show().content = document.createTextNode('Hello, LuLu UI!');
});
测试:
这里的dialog4.show()返回的是弹框元素自身,因此可以级联使用。原生弹框的show()方法返回的是undefined,不支持dialog4.show().content这种用法。
4. Dialog类设置内容
如果使用Dialog类创建弹框,则弹框的内容推荐使用content参数进行传递,例如:
new Dialog({
content: '#someId'
});
会自动把页面上id为'someId'的元素作为内容显示在弹框中。
实际开发,Dialog类的使用频率是最高的,因此接下来会专门对Dialog类进行介绍。
Dialog类使用指南
Dialog类本质是对常用的原生<dialog>元素的功能进行了封装,这样大家不必关心具体的细节,专注于API本身。
1. 起步
打开控制台,输入并执行下面这行JS:
new Dialog()
页面就会显示一个空弹框,并且返回当前<dialog>弹框元素。
因此下面代码中的eleDialog本质上就是<dialog>元素,<dialog>元素所有的属性和方法都可以直接使用。
let eleDialog = new Dialog()
例如eleDialog元素扩展的alert()方法就可以使用:
let eleDialog = new Dialog();
eleDialog.alert('我是提示内容');
当然,也可以级联使用:
new Dialog().alert('我是提示内容');
下面通过多个案例演示Dialog类的不同使用场景。
2. alert信息提示框
new Dialog().alert('操作成功!', {
type: 'success'
});
我们可以type参数指定提示的类型,其他内置类型还有:'remind'提示,'danger'警示。
也可以使用自定义的类型,例如:
代码如下:
button.addEventListener('click', function () {
new Dialog().alert('自定义提示,有标题,无图标。', {
title: '系统提醒',
type: 'custom'
});
});
3. confirm确认提示框
button.addEventListener('click', function () {
new Dialog().confirm('<h6>您确定要停用所选的成员吗?</h6><p>成员停用后,可以在停用成员列表中重新启用。</p>', {
buttons: [{
value: '停用',
events: function (event) {
// 按钮禁用
button.disabled = true;
// event.dialog是当前实例对象
event.dialog.remove();
}
}, {}]
});
});
我们可以使用buttons参数指定按钮的文案、类型以及事件。
4. 普通的内容弹框
new Dialog({
title: '普通文本框',
content: '我是一段HTML,啦啦啦啦啦',
buttons: [{
value: '知道啦!'
}]
});
5. 高度拉伸弹框
new Dialog({
title: '中间高度自适应的容器',
height: 'stretch',
content: `<div class="bg-white p20">${Array(60).fill().map((_, index) => {
return `<img src="${index}.gif" class="db mt10">`;
}).join('')}</div>`,
buttons: [{}]
});
通过设置参数height的值为'stretch'实现。最大支持高度为1000px,此值通过CSS进行修改。如果浏览器高度小于1000px,弹框高度会自动上下拉伸适配。
6. loading弹框
new Dialog().loading();
有时候,弹框内容是Ajax动态请求的,此时在Ajax成功之前是需要一个加载状态的。体验更好的做法是根据最终呈现布局,局部动态loading,但是有时候我们想要偷懒,不想再写一个loading布局,则就可以使用这里的loading弹框。例如下面这个示意:
代码如下:
button.addEventListener('click', function () {
let eleDialog = new Dialog({
width: 600
}).loading();
// ajax请求模拟
fetch(location.href).then(res => res.text()).then(text => {
eleDialog.setParams({
title: '请求内容',
buttons: [{}],
content: text.replace(/[\w\W]+<pre>([\w\W]+?)<\/pre>[\w\W]+/, '$1')
});
});
});
这里使用params参数让loading弹框替换成内容弹框。
7. 弹框打开DOM元素
下拉:
var target = document.getElementById('xxTarget');
button.addEventListener('click', function () {
// 如果弹框已创建,就直接显示
if (this.dialog) {
this.dialog.show();
} else {
target.classList.remove('dn');
this.dialog = new Dialog({
title: 'DOM载入测试',
content: target,
buttons: [{}, {}]
});
}
});
本例中,也可以直接使用ID选择器作为content参数值,例如:
new Dialog({
title: 'DOM载入测试',
content: '#xxTarget',
buttons: [{}, {}]
});
语法和参数
Dialog类的基础语法
基本的弹框使用方法为:
let eleDialog = new Dialog(options);
其中:
- options
options是可选参数,支持的参数见下表:
| 参数名称 | 支持类型 | 默认值 | 释义 |
|---|---|---|---|
| title | String | '' | 表示弹框的标题。 |
| content | String Object Function |
'' | 表示弹框显示的主体内容。可以是HTML字符串,或者是DOM对象,也可以是返回HTML字符串或DOM对象的函数。参数类型不同,弹框关闭的方法也不一样,DOM对象关闭执行hide()方法,HTML内容执行remove()方法。 |
| closable* | Boolean | true | 是否显示右上角的关闭按钮。 |
| buttons | Array | [] | 弹框的按钮元素。默认是空数组,表示没有按钮。每个按钮为一个{}对象,含一些可选参数,具体释义参见这里。
|
| width | String Number |
'auto' | 标题弹框的主体宽度。可以是纯数值,会按照像素单位处理;也支持其他任意单位,例如 默认值是 |
| height | String Number |
'auto' | 标题弹框的主体高度。可以是纯数值,会按照像素单位处理;也支持其他任意单位,例如 支持关键字 |
| onShow* | Function | function () {} | 弹框显示时候的回调。this为当前弹框元素,支持一个参数,为'show'事件对象。 |
| onHide* | Function | function () {} | 弹框隐藏时候的回调。this为当前弹框元素,支持一个参数,为'hide'事件对象。 |
| on |
Function | function () {} | 弹框移除时候的回调。this为当前弹框元素,支持一个参数,为'remove'事件对象。 |
后面跟随*的参数,为Dialog()方法独有的可选参数。其他扩展方法,无法重置。
buttons参数
buttons参数的数组项支持的参数如下:
{
type: '',
value: '',
form: '',
for: '',
className: '',
events: {}
}
其中:
| 参数名称 | 支持类型 | 默认值 | 释义 |
|---|---|---|---|
| type | String | 'primary' |
表示按钮的类型。和Button.css中按钮类型关键字对应。默认值与当前对象在buttons参数数组中的位置有关。第一个按钮对象,默认值是'primary',也就是蓝色按钮,也就是如果你的弹框只有一个按钮,默认是蓝色。之后的按钮,默认则是白色按钮,如白色的“取消”按钮。 |
| value | String | '确定' |
表示按钮的文字内容。默认值与当前对象在buttons参数数组中的位置有关。如果在数组的第一个选项中,默认值是'确定',如果在后面的选项,则按钮默认值是'取消'。 |
| form | String | '' | 表示按钮所属的表单元素的id,如果form属性值有设置,则按钮会自动变成'submit'类型,点击该按钮会触发对应表单元素的'submit'行为。 |
| for | String | '' | 如果设置此参数,弹框中的按钮会使用lable标签。此时,点击弹框按钮,会触发id值和此按钮for属性一致的控件元素的点击行为。此属性在一些特殊场景下,非常有用。例如,点击弹框按钮触发文件选择,又例如,点击弹框按钮触发页面中某个React按钮的执行。 |
| disabled | Boolean | false | 表示按钮是否处于禁用态。 |
| className | String | '' | 表示按钮上额外添加的类名。 |
| events | Object| |
{} | 表示按钮绑定的事件。可选,如果不设置,会调用弹框关闭事件。
如果只有click事件,可以直接使用Function类型参数,例如: events:
如果包含多个事件,则只能使用Object类型参数,例如: events: { |
因此:
1. 如果你的弹框默认就是一个文字为“确定”的确认按钮,则buttons参数内容就是:
{
buttons: [{}]
}
2. 如果你的弹框默认就是一个蓝色确认按钮,但是文字内容是“我知道了”,则buttons参数内容就是:
{
buttons: [{
value: '我知道了'
}]
}
3. 如果你的弹框默认就是一个文字为“确定”的确认按钮,但是是红色的警示按钮,则buttons参数内容就是:
{
buttons: [{
type: 'danger'
}]
}
4. 如果你的弹框默认就有一个蓝色“确定”按钮,和一个白色“取消”按钮,则buttons参数内容就是:
{
buttons: [{}, {}]
}
我们只需要空对象占位就好了。你也可以使用null占位。
5. form参数使用示意,点击下面的编辑小图标测试效果。
昵称:
相关代码如下:
昵称:<output>最帅最俊朗</output> <css-icon id="btnForm"></css-icon>
btnForm.addEventListener('click', function () {
let eleOutput = this.previousElementSibling;
new Dialog({
title: '修改昵称',
content: `<form id="editForm">
姓名:<input value="${eleOutput.textContent}" name="nickname" required>
</form>`,
buttons: [{
value: '修改',
form: 'editForm'
}],
onShow: function () {
this.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
// 输入框内容赋值
eleOutput.textContent = this.querySelector('[name="nickname"]').value;
// 弹框关闭
this.remove();
});
}
});
});
参数的底层设置
Dialog类中options参数的设置在底层是使用dialog.setParams()这个方法实现的。
dialog.setParams(options)
dialog.setParams()这个方法底层是使用Object.assign()这个方法实现的。
Object.assign(dialog.params, options || {})
因此,如果想要同时设置多个参数,下面这两种用法是等同的:
<dialog id="dialog5" is="ui-dialog">Hello, LuLu UI!</dialog>
button5.addEventListener('click', function () {
Object.assign(dialog5.show().params, {
title: '我是标题',
height: 400,
buttons: [{
value: '我是按钮'
}]
});
});
等同于:
button5.addEventListener('click', function () {
dialog5.show().setParams({
title: '我是标题',
height: 400,
buttons: [{
value: '我是按钮'
}]
});
});
测试:
如果需要设置的参数就1个或者2个,则可以使用更底层的方法,直接改变<dialog>元素的params属性值。
例如使用dialog.params.title设置弹框的标题。
<dialog id="dialog6" is="ui-dialog">Hello, LuLu UI!</dialog>
button6.addEventListener('click', function () {
dialog5.show().params.title = '我是标题-哇咔咔';
});
测试:
事件的底层处理
设置is="ui-dialog"的<dialog>元素除了支持原生的'close'事件,还支持'show'、'hide'、'remove'和'DOMContentLoaded'事件。
这些事件的用法很简单,直接对<dialog>元素添加对应的监听即可,例如:
dialog.addEventListener('DOMContentLoaded', event => {
console.log('弹框自定义属性和方法注册完毕了');
});
dialog.addEventListener('show', event => {
console.log('弹框显示了');
});
dialog.addEventListener('hide', event => {
console.log('弹框隐藏了');
});
dialog.addEventListener('remove', event => {
console.log('弹框移除了');
});
Dialog类中options的可选参数包括onShow、onHide和onRemove,其底层逻辑就是使用的上面的事件监听。
实际上,onShow参数并不是必须的,例如下面两段JS代码作用其实是一样的:
new Dialog({
content: `<form id="editForm"></form>`,
buttons: [{ form: 'editForm' }]
onShow: function () {
this.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
// 弹框关闭
this.remove();
});
}
});
等同于(不推荐这么使用):
let eleDialog = new Dialog({
content: `<form id="editForm"></form>`,
buttons: [{ form: 'editForm' }]
});
eleDialog.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
// 弹框关闭
this.remove();
});
因为new Dialog()执行的时候,弹框元素已经在页面中实现了,通过onShow设置显示的回调其实有些多余了。
Alert弹框语法
模拟浏览器window.alert()弹框。用法如下:
dialog.alert(content, alertOptions);
其中,dialog可以通过new Dialog()方法构造,也可以使用原生JS语句在页面中创建<dialog>元素。例如下面这种常用的用法:
let eleDialog = new Dialog(options).alert(content, alertOptions);
其中:
- options
- 可选。其中
onShow,onHide,onRemove这3个参数只能在这里设置。 - content
- 必须。提示的内容。支持HTML标签。
- alertOptions
- 可选。具体参数值见下表:
| 参数名称 | 支持类型 | 默认值 | 释义 |
|---|---|---|---|
| title | String | '' | alert弹框默认无标题文字,本项目,此参数不需要关心。 |
| type | String | 'remind' | alert弹框的类型, 参数包括'remind', 'success', 'warning', 'danger', 或者任意自定义'custom'。对应效果图缩略图如下:
|
| buttons | Array | [{}] | 表示按钮。默认为1个蓝色“确定”按钮。 |
实际开发用到可选参数场景并不多,多类似这样:
new Dialog().alert('弹弹弹,弹走鱼尾纹……');
Confirm弹框语法
模拟浏览器window.confirm()弹框。语法如下:
dialog.confirm(content, alertOptions);
其中,dialog可以通过new Dialog()方法构造,也可以使用原生JS语句在页面中创建<dialog>元素。例如下面这种常用的用法:
let eleDialog = new Dialog(options).confirm(content, confirmOptions);
其中:
- options
- 可选。其中
onShow,onHide,onRemove这3个参数只能在这里设置。 - content
- 必须。提示的内容。支持HTML标签。
- confirmOptions
- 可选。具体参数值见下表:
| 参数名称 | 支持类型 | 默认值 | 释义 |
|---|---|---|---|
| title | String | '' | 弹框的标题文字,默认无标题。 |
| type | String | 'danger' | 弹框的类型, 参数包括'remind', 'success', 'danger', 或者任意自定义'custom'。同Alert弹框,差别在于图标。 |
| buttons | Array | [{ type: 'danger' }, {}] |
表示按钮。默认为1个红色警示“确定”按钮和1个普通浅色按钮。 |
一般而言,我们需要对第1个警示按钮写事件,也就是确认删除之后干嘛干嘛,如:
new Dialog().confirm('确定弹弹弹,弹走鱼尾纹?', {
buttons: [{
events: function(event) {
/*
* 这里回调,巴拉巴拉小魔仙……
* ......
*/
// event.dialog为弹框实例对象
event.dialog.remove();
}
}, {}]
});
Loading弹框语法
语法如下:
let eleDialog = new Dialog(options).loading();
我们可以设定弹框的宽度以及各个回调。loading模式下,标题、关闭按钮、底部按钮都不可见,只有菊花转转转。此方法需要Loading.css,如果希望替换loading弹框内容,下面这些方法都是可以的:
dialog.content = newContent;
dialog.params.content = newContent;
dialog.setParams({
content: newContent;
});
newContent可以是任意的字符串、DOM节点或者返回字符串或DOM节点的Function函数。
暴露的属性和方法
eleDialog就是<dialog>弹框元素,暴露了下面这些属性和方法:
{
// 只读
element: {
// 含半透明遮罩的容器
container: null,
// 弹框主体元素
dialog: null,
// 弹框标题元素
title: null,
// 弹框关闭按钮
close: null,
// 弹框主内容元素
body: null,
// 弹框底部元素
footer: null,
// 弹框按钮1(如果有)
button0: null,
// 弹框按钮2(如果有)
button1: null
},
// 可读可写
params: {
title: '',
width: 'auto',
height: 'auto',
buttons: [],
content: ''
},
// 参数设置
setParams: function (options) {},
// 一些格式化的方法
alert: function () {},
confirm: function () {},
loading: function () {},
// 弹框显示
show: function () {},
// 弹框隐藏
hide: function () {},
// 弹框移除
remove: function () {}
}
本页贡献者:
zhangxinxu