本主题已经彻底取消了传统的基于回调参数的事件处理方法,全部改成基于 DOM 原生事件或 DOM 自定义事件的处理方式。
原生事件
Edge主题更进一步,彻底降低了 UI 组件的存在感,也就是开发者在进行交互开发的时候,只需要按照原生的 HTML 控件元素开发即可。
其实现的底层逻辑在于,当 LuLu UI 创建的组件在发生交互的时候,会触发原始 HTML 控件元素的原生事件,最具有代表性的就是 'change'
事件,部分 UI 组件还支持 'input'
事件。
以 <select>
下拉框元素具体,在实际开发的时候,我们无需关心下拉框组件的初始化以及交互逻辑判断,只需要把对应的 <select>
元素写在页面中就可以了,就像下面这样:
<select is="ui-select"> <option value="1">选项1</option> <option value="2">选项2</option> </select>
开发者无需再做任何其他事情,就当 LuLu UI 组件不存在正常开发就好了。
比方说用户选择了某个选项,想要进行处理,则使用原生的 'change'
事件就好了,语法也是原生的 DOM 事件处理语法,例如:
select.addEventListener('change', function () {
// 下拉框选择了
});
无论是 Color 颜色选择组件、Datetime时间选择组件、Range范围选择组件还是Datalist数据列表组件,都是一样的处理。
自定义事件
Edge主题支持若干固定的自定义事件,包括 'show'
、'hide'
、'select'
、'success'
等事件,具体参见下表:
组件名 | 自定义事件 | 说明 |
---|---|---|
Select下拉框 | - | - |
Range范围选择 | - | - |
Color颜色选择 | 'show'、'hide' | 颜色选择面板显示和隐藏的时候触发。 |
Datetime日期选择 | 'show'、'hide' | 日期选择面板显示和隐藏的时候触发。 |
Datalist数据列表 | 'show'、'hide'、'select' | select 事件发生于列表内容选择后。 |
Dialog弹框 | 'show'、'hide'、'close'、'remove' | show 事件在弹框显示的时候触发,hide 事件在弹框隐藏的时候触发,close 事件在弹框关闭的时候触发,remove 事件在弹框移除的时候触发。
其中,hide 事件和 close 事件的区别在于,当执行 |
Tip提示 | 'show'、'hide' | 提示信息显示和隐藏的时候触发。 |
ErrorTip出错提示 | 'show'、'hide' | 出错提示信息显示和隐藏的时候触发。 |
LightTip轻提示 | - | - |
Pagination分页 | 'change' | 选择不同分页数量的时候触发 change 事件。 |
Drop下拉 | 'show'、'hide' 'select' 'ensure'、'cancel' |
select 事件是 Drop 下拉扩展的 list() 列表方法专有;ensure 和 cancel 事件是 Drop 下拉扩展的 panel() 轻面板方法才会触发,只有当 target 对象是 <dialog> 元素的时候才会执行。 |
Tab切换 | 'show'、'hide'、'switch' | 无论选项卡按钮激活或失活都会触发 switch 事件。 |
Validate表单验证 | 'valid' | 表单元素全部验证通过时候触发 valid 事件。 |
Table列表 | 'show'、'check' | show 事件是列表内容显示的时候触发,check 事件是列表中的复选框(如果有)选中的时候触发。 |
Form表单 | 'success'、'error'、'complete' | success 事件在表单请求提交成功后触发,error 是失败后触发,complete 事件在请求完成后触发,无论成功还是失败。 |
同一个元素可能会同时应用多个 UI 组件,这就会带来同一种类型的事件互相冲突的问题,例如一个输入框即是日期选择框,又参与了出错验证,此时,日期选择框出现和出错提示出现都会触发 show 事件,可能会对业务开发带来困扰,此时可以根据 event.detail.type
判断 show 事件是哪个组件触发的。
例如:
点击日期选择框,或者点击“验证”按钮,控制台就会看到对应组件类型的提示,相关测试代码如下所示:
<input type="date" id="date" is="ui-datetime"> <button type="primary" id="valid" is="ui-button">验证</button>
valid.addEventListener('click', function () { date.errorTip('测试提示信息'); }); date.addEventListener('show', function (event) { console.log(`显示的 UI 组件类型是 ${event.detail.type}`); });
生命周期事件
几乎所有的 UI 组件都提供了 'connected' 和 'DOMContentLoaded' 这两个生命周期事件,具体的含义见下表。
事件类型 | 描述 |
---|---|
connected | connected 事件在 UI 组件和文档上下文发生接触的时候触发 |
DOMContentLoaded | DOMContentLoaded 事件在 UI 组件的 DOM 结构在页面中初始化完毕触发 |
举个例子,<ui-pagination>
是个自定义元素,当我们使用 JavaScript 创建一个 <ui-pagination>
元素的时候,上面两个生命周期事件均不会触发。
// 不会触发声明周期事件
let p = document.createElement('ui-pagination')
但是如果将对象 p
附加在页面中,此时,就会触发 connected 事件,表示元素和页面发生了连接。
// 触发 connected 事件
document.body.append('p');
那 DOMContentLoaded 事件什么时候触发呢?
当 <ui-pagination>
分页完整的 DOM 结构创建之后触发。
为什么需要生命周期事件?
因为有时候我们需要一进入页面就对 UI 组件元素进行某些属性修改,如果此时 UI 组件元素还只是普通的 DOM 元素,则进行的这些属性修改可能无法触发对应的变化。
举个例子,页面中直出了一个 <ui-pagination id="p2">
元素,如果此时 Pagination.js 还未加载完毕就设置 p2.total = 100
是无效的,因为此时 <ui-pagination>
元素还未注册,组件内置的属性和功能尚未挂载。
有了生命周期事件,则就不需要担心加载的时机问题,直接在 connected 事件中设置就可以了,示意:
p2.addEventListener('connected', function (event) {
// 分页总数就会变化
this.total = 100;
});
对于内置自定义元素,Safari浏览器是不支持的,需要引入一段 Polyfill 代码,但是这段代码的执行是滞后的,会导致内置自定义元素注册的时机比 Chrome 浏览器靠后,所带来的后果就是 Chrome 浏览器下正常运行的代码在 Safari 浏览器下出现的报错。
原因就在于代码执行的时机出了问题,可以在 connected 事件或 DOMContentLoaded 事件中执行相关的代码,可以让 Safari 浏览器也能正常执行。
另外补充一点,如果生命周期事件在组件已经完成注册后再设置,是不会触发的,就好比浏览器原生的 DOMContentLoaded 事件,如果页面已经完全加载完毕,你再去绑定, DOMContentLoaded 事件并不会触发。
我们可以使用自定义元素上暴露的 isConnectedCallback 属性判断自定义元素是否已经完成注册。
// 如果已经完成注册,直接设置
// 否则,设置生命周期函数,在注册完成后执行设置
if (p2.isConnectedCallback) {
p2.total = 100;
} else {
p2.addEventListener('connected', function (event) {
this.total = 100;
});
}
其他判定是否完成注册的方法
对于自定义元素,我们可以使用 :defined
伪类判断组件是否完成初始化。
例如:
<ui-drop id="d0">下拉</ui-drop>
console.log(d0.matches(':defined'));
// 如果返回 true 说明完成了注册,
// 如果返回 false,则说明组件没有完成注册
对于内置自定义元素,非 Safari 浏览器也可以使用 :defined
伪类判断。
对于自定义属性元素,:defined
则无效,无法作为判断依据,此时可以根据元素上的 [defined]
属性继续进行判断。
本页贡献者:
zhangxinxu