安装与调用
如果是基本弹框功能,直接引用下面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