隐藏细节

所谓隐藏细节,指的是文档中并未体现,需要查看源码才知晓的细节知识,在组件的高阶应用中,这些细节可以帮助开发者更好的进行开发。

键盘快捷键

如果大家单独引入某一个 UI 组件库,建议同时引用 Keyboard.css 和 Keyboard.js,对组件的键盘访问做了非常完善的支持。

<link rel="stylesheet" href="https://unpkg.com/lu2/theme/edge/css/common/ui/Keyboard.css">
<script href="https://unpkg.com/lu2/theme/edge/js/common/ui/Keyboard.js"></script>

如果大家引入的是 ui.css 和 all.js,则无需上面的处理,因为默认包含在内了。

Keyboard.js 对常用的 Tab/Shift+Tab、Esc、Enter 等键盘操作进行了处理,包括:

  • 合理的索引顺序变化,例如弹框显示的时候,索引焦点会聚焦到弹框上,弹框关闭后,焦点位置还原;
  • 所有带有浮层性质的 UI 组件可以使用 Esc 进行隐藏处理;
  • 优化了按钮、链接点击和聚焦不同行为下的样式处理;

以上是大家可能知道的,下面讲讲其他隐藏的细节知识。

判断某行为是否键盘触发

鼠标点击按钮可以显示下拉,键盘聚焦按钮回车也可以显示下拉,此时,交互场景不同,列表显示的 UI 也应该有所不同,在键盘交互场景下,应该高亮控件元素。

在 CSS 中,类似的样式处理可以交给 :focus-visible 伪类,不过这个伪类兼容性目前还不够,需要使用 JS 进行判断处理,Keyboard.js 暴露了一个全局属性 isKeyEvent,可以判断当前语句的执行是否与键盘行为相关,例如:

if (window.isKeyEvent) {
    // 键盘操作触发                
} else {
    // 点击操作触发
}

accesskey属性的支持

引入 Keyboard.js 后,用来自定义快捷键的 accesskey 属性得到了更好的支持。

例如有如下 HTML:

<form id="f0" is-validate>
    <input type="search" class="ui-input" accesskey="/" required>
    <button type="submit" class="ui-button" data-type="primary" accesskey="s">搜索</button>
</form>

搜索框这里设置了 accesskey="/",此时大家只要按下键盘的 / 键,搜索框就会被聚焦;搜索按钮设置了 accesskey="s",此时大家只要按下 S 键,搜索按钮就会聚焦,而按下 Alt + S (Mac 下是 Control + Option + S)键,就会触发搜索表单提交(通过触发提交按钮的点击行为触发)。

下面就是对应的测试表单,大家可以按下 / 键、 S 键或组合键试一试。

另外,按下 shift + ? 会出现页面中所有 accesskey 快捷键内容的提示。

隐匿的公开方法

部分 UI 组件其实以公开或半公开的方式暴露了一些与 UI 样式无关的 JavaScript 方法,当大家引入对应的 UI 组件后,这些方法是可以直接拿来使用的,包括下面这些。

Color 颜色选择

Color 颜色选择组件暴露了几个颜色转换相关的静态方法。

方法名 说明 参数和返回值
Color.funHslToHex(h, s, l, a) 任意的 hsl(a) 色值转换成 #rrggbb(aa) 格式的色值。例如:
Color.funHslToHex(1/3, 0.5, 0.5, .6)
// 返回值是 "40bf4099"
h, s, l, a这4个参数范围均是0-1。
Color.funHexToHsl(hex) hex 色值表示转 hsl() 函数表示。例如:
Color.funHexToHsl('#468be0')
// 返回值是 [0.592, 0.712963, 0.57647]
Color.funHexToHsl('468b');
// 返回值是 [0.5833, 0.3333, 0.4, 0.7333]
参数 hex 类型为字符串,必需,返回值是数组,数组项的数值范围均是0-1。
Color.funRgbToHex(rgb) rgb() 函数色值转 hex 色值。例如:
Color.funRgbToHex('rgb(50, 255, 50)')
// 返回值是 "#32ff32"
Color.funRgbToHex('rgba(128, 10, 10, .75)')
// 返回值是 "#800a0abf"
参数 rgb 类型为字符串,必需。

Datetime 时间选择

Datetime 时间选择组件在字符串、日期对象上扩展了几个 Nottifill 性质的方法。

扩展名称 说明 参数和返回值
String.prototype.toTime() 时间字符串转换成格式符合的时分秒数组。例如:
'12:3:9'.toTime()
// 返回值是 ["12", "03", "09"]
返回值是数组,会自动补零。
String.prototype.toDate() 将字符串日期格式转换成日期对象。例如:
'2019-03-23'.toDate()
// 返回值等同于 new Date(2019, 2, 23)
'2022年8月9日'.toDate()
// 返回值等同于 new Date(2022, 7, 9)
返回是是 Date 对象数据类型。
Date.prototype.toArray() 将日期对象转换成包含年月日信息的数组。例如:
new Date(2022, 8, 9).toArray()
// 返回值是 [2022, "09", "09"]
返回值是数组,如果月份和日期不足 10,会自动补零。

Datalist 数据列表

Datalist 数据列表也暴露了若干静态方法,主要是字符的转义和反转义处理。

方法名 说明 参数和返回值
Datalist.stripHTML(str) 过滤 HTML 标签字符串。例如:
Datalist.stripHTML('<script>alert(1)</script>')
// 返回值是 "alert(1)"
返回值是过滤后的字符串。
Datalist.encodeHTML(str) 转义 HTML 标签字符串。例如:
Datalist.encodeHTML('<script>')
// 返回值是 "<script>"
返回值是转义后的字符串。
Datalist.decodeHTML(str) 反转义 HTML 标签字符串。例如:
Datalist.decodeHTML('&lt;script&gt;')
// 返回值是 "<script>"
返回值是反转义后的字符串。

Table 列表解决方案

Table 列表解决方案内置了一个基于 ES6 模板字符串原生能力的模板解析方法 interpolate。

扩展名称 说明 参数和返回值
String.prototype.interpolate(params) 可以使用 ES6 模板字符串进行模板解析。例如已知模板元素:
<template id="tpl">
<ol>${data.map((value, index) => {
  return `<li>${value}-${index}</li>`
}).join('')}</ol>
</template>

此时就可以使用 interpolate 方法对上述 HTML 模板字符串进行解析渲染。

tpl.innerHTML.interpolate({
  data: ['L', 'U', 'I']    
})
// 返回值是 "<ol><li>L-0</li><li>U-1</li><li>I-2</li></ol>"
返回值是渲染后的字符串数据。

其他

1. 底层定位方法

LuLu UI 组件中所有的浮层定位的底层调用都是一样的,全部都是使用的 Follow.js 中的 DOM 扩展方法。

有时候,处于业务需要,我们需要手动进行定位交互,此时,就可以使用 Follow.js 提供的定位方法。

例如有如下 HTML 结构:

<button id="b0" type="primary" is="ui-button" is-follow="img0">多次点击我</button>
<img id="img0" src="logo.svg" hidden>

希望点击按钮的时候图片切换显示,就可以使用下面的代码:

b0.addEventListener('click', function () {
    if (img0.clientWidth == 0) {
        img0.style.display = 'block';
        // 相对按钮定位
        this.follow({
            offsets: {
                x: 0,
                y: 10
            }
        });
    } else {
        img0.style.display = 'none';
    } 
});
实时效果:
2. 层级设置

基本上,所有的弹框和浮层都内置了层级顶层设置方法,方法名都是一样的,是 element.zIndex()

如果是弹框元素,则执行下面的代码可以让弹框元素层级最高:

dialog.zIndex();

如果是 Drop 下拉元素,则代码为:

drop.element.target.zIndex();

所有组件默认会执行层级最高方法,因此,大多数场景下,大家并不需要知道上面的细节,只有某些特殊场景,需要手动设置位于下层的元素到顶层,就需要用到这里的 zIndex() 方法。

3. 输入增强

在表单验证中,所有的输入框(包括多行输入框)都内置了粘贴和拖移的增强处理,例如去前后空格,手机或邮箱格式化等,但这在 React 下可能会有粘贴不触发 Input 事件的问题,此时,可以设置 data-enhance="false" 关闭此增强处理。

<textarea class="ui-textarea" data-enhance="false"></textarea>
本页贡献者:

zhangxinxu