级联选择
多级联动选择(省市区、分类树)。数据写成页面里的嵌套列表,或用 ZhaoUI.cascader 传一棵树。支持搜索、悬停展开,窄屏自动变成逐级下钻。
带行为 分包 modular/select 1 个事件 3 个方法
示例
- 浙江
- 杭州
- 西湖区
- 余杭区
- 宁波
- 海曙区
- 鄞州区
- 杭州
- 江苏
- 南京
- 玄武区
- 南京
- 海南
- 海口
- 龙华区
- 海口
代码
<div data-zh-cascader data-name="region" data-searchable data-value="浙江/杭州/西湖区" data-placeholder="请选择地区" aria-label="地区">
<ul hidden>
<li>浙江
<ul>
<li>杭州<ul><li>西湖区</li><li>余杭区</li></ul></li>
<li>宁波<ul><li>海曙区</li><li>鄞州区</li></ul></li>
</ul>
</li>
<li>江苏<ul><li>南京<ul><li>玄武区</li></ul></li></ul></li>
<li data-disabled>海南<ul><li>海口<ul><li>龙华区</li></ul></li></ul></li>
</ul>
</div>
<div id="cas2"></div>
<script>
document.querySelector('[data-zh-cascader]').addEventListener('zh:cascader-change', function (e) {
console.log(e.detail.text); // 浙江 / 杭州 / 西湖区
});
ZhaoUI.cascader('#cas2', {
expandTrigger: 'hover',
data: [{ label: '前端', value: 'fe', children: [{ label: 'Vue', value: 'vue' }, { label: 'React', value: 'react' }] }],
onChange: function (labels, text, nodes) { console.log(nodes.map(function (n) { return n.value; })); }
});
</script>只用核心包(modular/core)时,还要加 modular/select.min.js 和 modular/select.min.css;全量版已包含。见 按需引入。
属性
| 属性 | 用在 | 取值 | 说明 |
|---|---|---|---|
data-zh-cascader | 容器 <div> | 无 | 声明这是一个级联选择;容器里的第一个 <ul> 是数据,读取后会被替换成控件 |
data-name | 容器 | 字段名 | 生成一个隐藏 <input name=…> 参与表单提交,值是用 / 连接的路径(如 浙江/杭州/西湖区);如果路径上每个节点都写了 data-value,则用 data-value 连接 |
data-value | 容器 | 用 / 连接的标签路径,如 浙江/杭州/西湖区 | 初始选中的路径;标签里含有 / 时请改用命令式 |
data-placeholder | 容器 | 字符串 | 占位文字,默认「请选择」 |
data-searchable | 容器 | 布尔属性 | 可输入搜索,匹配完整路径文字,只搜到叶子节点 |
data-clearable | 容器 | false 表示关闭 | 默认有清除按钮 |
data-expand-trigger | 容器 | click(默认)| hover | 悬停展开下一级;触屏和窄屏始终是点击 |
data-size | 容器 | sm | md(默认)| lg | 尺寸 |
data-sep | 容器 | 字符串,默认「 / 」 | 输入框里各级之间的分隔文字 |
data-labelledby | 容器 | 标签元素的 id | 无障碍名称;也可以直接写 aria-label |
data-disabled / data-value | <li> | 布尔属性 / 字符串 | 禁用该节点及其子树 / 该节点的值(用于表单) |
<label for="容器 id"> | 容器所在页面的 <label> | for 指向容器的 id | label 会成为输入框的无障碍名称,点击 label 会聚焦输入框;容器是空 <div>,label 的 for 指向它的 id 即可 |
事件
| 事件 | 触发于 | detail | 说明 |
|---|---|---|---|
zh:cascader-change | 容器 | { path, text, nodes } | 选中或清除后触发(冒泡)。path 是标签数组,text 是拼好的文字,nodes 是节点对象数组(能读到你自己加的字段,如 value);清除时都是空的 |
方法
ZhaoUI.cascader(host, { data, value, searchable, clearable, expandTrigger, size, placeholder, sep, labelledby, onChange }):命令式创建。data 是节点树 [{ label, children?, disabled?, …你的字段 }];value 是标签数组;onChange(labels, text, nodes)el.zhCascader.get() / .getNodes():读取当前路径的标签数组 / 节点对象数组el.zhCascader.set(labels) / .setData(tree) / .open() / .close():设置路径(不触发 change,并同步隐藏字段)、更换数据、打开、关闭
样式类
zh-sel zh-cas-panel zh-cas-col zh-cas-item
无障碍
- 输入框是 role="combobox",各级是 role="listbox",带 aria-selected 与 aria-activedescendant
- ↓ ↑ 在当前一级移动(跳过禁用项),→ 展开子级,← 回到上一级,Enter 选中叶子或展开分支,Esc / Tab 关闭
- 搜索时 ↓ ↑ 在结果里移动,Enter 选中;结果显示完整路径
- 窄屏(≤ 767px)改为逐级下钻,有「返回上一级」按钮,每一级都是整行的大点击区
- 禁用的节点标记 aria-disabled,不可展开也不可选
常见问题
级联选择是什么?
多级联动选择(省市区、分类树)。数据写成页面里的嵌套列表,或用 ZhaoUI.cascader 传一棵树。支持搜索、悬停展开,窄屏自动变成逐级下钻。
怎么使用级联选择?
先在页面里引入 zhaoui.css 和 zhaoui.js(放在 </body> 前,不加 defer),再照本页「用法」里的标记书写;需要用代码控制时,用「方法」里列出的接口。
级联选择有哪些事件?
zh:cascader-change(选中或清除后触发(冒泡)。path 是标签数组,text 是拼好的文字,nodes 是节点对象数组(能读到你自己加的字段,如 value);清除时都是空的)。
级联选择有哪些方法?
ZhaoUI.cascader(host, { data, value, searchable, clearable, expandTrigger, size, placeholder, sep, labelledby, onChange }):命令式创建。data 是节点树 [{ label, children?, disabled?, …你的字段 }];value 是标签数组;onChange(labels, text, nodes);el.zhCascader.get() / .getNodes():读取当前路径的标签数组 / 节点对象数组;el.zhCascader.set(labels) / .setData(tree) / .open() / .close():设置路径(不触发 change,并同步隐藏字段)、更换数据、打开、关闭。
级联选择支持键盘和读屏吗?
输入框是 role="combobox",各级是 role="listbox",带 aria-selected 与 aria-activedescendant;↓ ↑ 在当前一级移动(跳过禁用项),→ 展开子级,← 回到上一级,Enter 选中叶子或展开分支,Esc / Tab 关闭;搜索时 ↓ ↑ 在结果里移动,Enter 选中;结果显示完整路径。
级联选择需要依赖框架吗?
不需要。ZhaoUI 是原生 HTML、CSS 和 JavaScript,不依赖 jQuery、Vue 或 React。