93 lines
4.5 KiB
JSON
93 lines
4.5 KiB
JSON
{
|
||
"slug": "listpicker",
|
||
"end": "html",
|
||
"curated": true,
|
||
"summary": "原生 H5 多选下拉列表:容器挂 data-listpicker,交互靠 data-val / data-rm 钩子与 is-* 状态类。",
|
||
"usage": [
|
||
"页面只留空容器 <div class=kole-listpicker data-listpicker>,脚本用 querySelectorAll 遍历初始化,一页可挂多个实例。",
|
||
"触发区与弹层全部由脚本 createElement / innerHTML 生成,HTML 里看不到静态结构,改版式要动 renderTrigger 与 renderPanel。",
|
||
"单个选项靠 .kole-listpicker-option 上的 data-val 携带它的值,点击时读 opt.dataset.val 再翻转 value 数组整块重绘。",
|
||
"已选标签里的删除叉用 data-rm 标记,trigger 的点击处理里用 e.target.closest 判断这次点击是删标签还是开合下拉。",
|
||
"选中态加 is-checked、禁用项叠 is-disabled、展开时给 trigger 加 is-open,三个状态类全由脚本按数据 toggle。",
|
||
"点击组件外部收起靠 document 上的 click 监听加 root.contains 判断,因为面板每次整块重绘,监听不会重复叠加。"
|
||
],
|
||
"bestPractices": [
|
||
"trigger 上静态写了 role=button 与 aria-expanded=false,但脚本只切换 is-open 类,没有同步 aria-expanded 真值,接入时要自己补 setAttribute。",
|
||
"全选按钮写作 .kole-listpicker-selectall 且不带 data-* 钩子,脚本按类名定位;同一容器重复初始化会绑到上一轮留下的旧节点。",
|
||
"搜索框在每次 renderPanel 时重建,输入焦点会丢,连续输入只能靠 input 事件驱动的整块重绘这条路径。"
|
||
],
|
||
"apiCarrier": {
|
||
"kind": "attrs",
|
||
"note": "HTML 端没有 props 概念,四类载体并用:data-listpicker 负责挂载、data-val 与 data-rm 负责行级取值、kole-* 类名定结构、is-* 状态类表状态。",
|
||
"table": [
|
||
{
|
||
"name": "data-listpicker",
|
||
"type": "存在即挂载",
|
||
"desc": "初始化钩子,脚本遍历所有带该属性的容器各自建实例"
|
||
},
|
||
{
|
||
"name": "data-val",
|
||
"type": "选项的 value 字符串",
|
||
"desc": "落在 .kole-listpicker-option 上,点击时作为该选项的值读取"
|
||
},
|
||
{
|
||
"name": "data-rm",
|
||
"type": "标签的值字符串",
|
||
"desc": "落在标签内的删除叉上,closest 命中即表示这次点击是移除该标签"
|
||
},
|
||
{
|
||
"name": "kole-listpicker-option",
|
||
"type": "类名",
|
||
"desc": "单个可选行,选中时叠加 is-checked,禁用时叠加 is-disabled"
|
||
},
|
||
{
|
||
"name": "kole-listpicker-selectall",
|
||
"type": "类名",
|
||
"desc": "面板里的全选行,点击把过滤后的可见项并入选中集合"
|
||
},
|
||
{
|
||
"name": "kole-listpicker-tag",
|
||
"type": "类名",
|
||
"desc": "触发器里已选项的标签,内部含 data-rm 删除叉"
|
||
},
|
||
{
|
||
"name": "kole-listpicker-search",
|
||
"type": "类名",
|
||
"desc": "面板顶部搜索容器,内含原生 input"
|
||
},
|
||
{
|
||
"name": "is-open",
|
||
"type": "状态类",
|
||
"desc": "挂在 trigger 上表示下拉展开,由脚本关闭 / 展开时 toggle"
|
||
}
|
||
]
|
||
},
|
||
"a11y": [
|
||
"挂载容器本身是空 div,语义全靠脚本生成的 trigger 上的 role=button 与 aria-haspopup=listbox 撑着。",
|
||
"trigger 有 tabindex=0 可聚焦,但没有绑定任何键盘事件,回车或空格不会展开下拉,方向键也不移动高亮。",
|
||
"选项是 div 加 click,既无 role=option 也无 aria-selected,选中信息只在 .box 里显示 ✓ 字符。",
|
||
"展开时焦点不移入搜索框,aria-expanded 也不更新,键盘用户得不到展开反馈。"
|
||
],
|
||
"resources": [
|
||
{
|
||
"file": "frameworks/ListPicker.html",
|
||
"kind": "HTML 实现",
|
||
"desc": "ListPicker.html —— 本端实现全文,含结构与交互逻辑"
|
||
},
|
||
{
|
||
"file": "frameworks/ListPicker.css",
|
||
"kind": "样式文件",
|
||
"desc": "frameworks/ListPicker.css —— 组件全部 kole-* 类名与 is-* 状态类的样式定义"
|
||
}
|
||
],
|
||
"exampleIds": [
|
||
"listpicker-ex-1"
|
||
],
|
||
"notes": [
|
||
"挂载点见 frameworks/ListPicker.html:24,批量初始化见第 96 行。",
|
||
"data-val 见 frameworks/ListPicker.html:65,data-rm 见第 47 行。",
|
||
"trigger 的 role 与 aria 属性见 frameworks/ListPicker.html:42,is-open 切换见第 50 行。",
|
||
"契约声明 filterable,HTML 端无同名属性,搜索框固定渲染,属实现与契约的差异。"
|
||
]
|
||
}
|