1、开始
【介绍】始于 Layui 下拉选的多选解决方案 formSelects,由于渲染速度慢,代码冗余,被放弃了。
xm-select 使用了新的开发方式,利用 preact 进行渲染,大幅度提高渲染速度,并且可以灵活扩展。
【作者】maplemei, 热爱前端的 Java 程序猿, 如果喜欢作者的插件, 可以请作者吃雪糕。
2、下载
git clone https://gitee.com/maplemei/xm-select.git
3、快速示例
4、配置项与方法
el
【说明】渲染对象,CSS 选择器,DOM 元素。
【类型】{string}
【可选值】-
【默认值】-
language
【说明】语言选择
【类型】{string}
【可选值】zn/en
【默认值】zn (中文)
data
【说明】显示的数据
【类型】{array|function}
【可选值】-
【默认值】[]
【子项】是对象格式,具体见 prop
content
【说明】自定义下拉框 html
【类型】{string}
【可选值】-
【默认值】-
initValue
【说明】初始化选中的数据(需要设置在 data 子项中存在的 value 值。)
【类型】{array}
【可选值】-
【默认值】null
tips
【说明】默认提示,类似于 placeholder
【类型】{string}
【可选值】-
【默认值】‘请选择’
empty
【说明】空数据提示
【类型】{string}
【可选值】-
【默认值】‘暂无数据’
filterable
【说明】是否开启搜索 (默认按照子项的 name 属性值进行搜索)
【类型】{boolean}
【可选值】true/false
【默认值】false
searchTips
【说明】搜索提示
【类型】{string}
【可选值】-
【默认值】请选择
delay
【说明】搜索延迟 ms
【类型】{int}
【可选值】-
【默认值】500 (一般使用默认值即可)
filterMethod
【说明】搜索回调函数
【类型】{function}
callback(val, item, index, prop)
- val: 当前搜索值(data 数组内子项);
- item: 每个 option 选项;
- index: 位置数据中的下标;
- prop:定义 key;
return true 显示在搜索结果;
return false 不显示~;
【可选值】-
【默认值】-
filterDone
【说明】搜索完成函数
【类型】{function}
callback(val, list)
- val: {string} 当前搜索值;
- list: {array} 过滤后的数据;
【可选值】-
【默认值】500
remoteSearch
【说明】 是否开启自定义搜索(远程搜索)
【类型】{boolean}
【可选值】true/false
【默认值】false
remoteMethod
【说明】 自定义搜索回调函数
【类型】{function}
callback(val, cb, show, pageIndex)
- val: 当前搜索值;
cb
(arr, totalPage): 回调函数,- arr: 数组,结构同 data;
- totalPage: 远程分页,总页码;
- show: 下拉框显示状态;
- pageIndex: 分页下当前页码;
【可选值】true/false
【默认值】false
【注意】这个钩子默认初始就会触发一次
(所以 data 默认给 [])。
【示例】
自定义搜索(远程搜索)
direction
【说明】 下拉方向
【类型】{string}
【可选值】‘auto’/‘up’/‘down’
【默认值】‘auto’
style
【说明】自定义样式
【类型】{object}
【可选值】-
【默认值】{}
【结果】样式会被添加在 xm-select 标签上。
height
【说明】默认最大高度
【类型】{string}
【可选值】-
【默认值】200px
【结果】会添加 style=“max-height: xxxpx;” 的值到 class=“scroll-body” 上。
paging
【说明】是否开启自定义分页
【类型】{boolean}
【可选值】true/false
【默认值】false
pageSize
【说明】分页条数
【类型】{int}
【可选值】-
【默认值】10
pageEmptyShow
【说明】分页无数据是否显示
【类型】{boolean}
【可选值】true/false
【默认值】true
pageRemote
【说明】是否开启远程分页
【类型】{boolean}
【可选值】true/false
【默认值】true
radio
【说明】是否开启单选模式
【类型】{boolean}
【可选值】true/false
【默认值】false
repeat
【说明】是否开启重复性模式
【类型】{boolean}
【可选值】true/false
【默认值】false
clickClose
【说明】是否点击选项后自动关闭下拉框
【类型】{boolean}
【可选值】true/false
【默认值】false
prop
【说明】自定义属性名称
【类型】{object}
【值】
- name 键:{string} 显示名称 (def) name
- value 键:{string} 选中值,当前多选唯一 (def) value
- selected 键:{string} 是否选中 (def) selected
- disabled 键:{string} 是否禁用 (def) disabled
- children 键:{string} 分组 children (def) children
- optgroup 键:{string} 分组 optgroup (def) optgroup
【特殊】
// 若 children 属性为数组时开启分组模式
const obj = {
name: '销售员',
children: [
{ name: '李四', value: 4, selected: true },
{ name: '王五', value: 5 },
],
}
// 可在分组上定义 click 属性,来定义点击事件
const obj1 = {name: '选中', children: [...], click: 'SELECT'},
const obj2 = {name: '清空', children: [...], click: 'CLEAR'},
const obj3 = {name: '自动', children: [...], click: 'AUTO'},
const obj4 = {name: '自定义', children: [...], click: function(item){
// ({ children, click, name, optgroup })
/*
children: 子项;
click: 点击事件函数
name: 名称
optgroup:是否分组
*/
alert('自定义的, 想干嘛干嘛');
}}
theme
【说明】主题配置
【类型】{object}
【值】
- color 键:{string} 主题颜色 (def) #009688
- maxColor 键: {string} 选中上限闪烁边框颜色 (def) #e54d42
- hover 键: {string} 键盘操作的背景色 (def) #f2f2f2
model
【说明】模型,多选的展示方式,具体见下面:
【类型】{object}
【值】目前仅配置 label 即可
- label 字段:配置插件显示方式;
- type 字段:设置显示方式。(需要和下面字段(含自定义)配置使用)
- ‘block’: (def) 默认方块显示;
- ‘text’: 使用字符串拼接的方式; (left, right, separator 分别配置左右中间分隔符)
- ‘xxx’:自定义;
- block 字段:使用方块的设置;
- showCount 字段:设置最大显示数量。0: 不限制
- type 字段:设置显示方式。(需要和下面字段(含自定义)配置使用)
const options = {
model: {
/*
1、【icon 字段】设置 是否展示 复选框或者单选框 图标。
'show': (def) 默认展示图标。
'hidden': (def) 隐藏图标,变为整行的背景色填充;。
*/
icon: 'show',
// 2、label 字段:设置标签`使用`方式。
label: {
// 设置块显示 ----------------------------- start
/*
3、【type 字段】设置显示方式
type: 'block' 设置块显示。(即:下拉选以 “有图标的” 复选框/单选框显示)
*/
type: 'block',
/*
4、【block 字段】块显示一些配置
showCount 字段:最大显示数量。(def) 0:表示不限制~。
showIcon 字段:是否显示删除图标。(def) true
template 字段: 自定义渲染 label。
{function} callback(item, sels) data: 所有的数据;sels:选中的数据;
(def) 默认渲染 data 子项目中 name 对应的值。
*/
block: {
showCount: 0,
showIcon: true,
template: null,
},
// 设置块显示 ----------------------------- end
// 设置文本显示 ----------------------------- start
/*
5、【type 字段】设置显示方式
type: 'text' 设置纯文本显示。(即:下拉选中项,只显示文本)
*/
type: 'text',
// 使用字符串拼接的方式
/*
6、【text 字段】文本显示一些配置
left 字段:左边拼接的字符;
right 字段:右边拼接的字符;
separator 字段:中间的分隔符;
*/
text: {
left: '【',
right: '】',
separator: ',',
},
// 设置文本显示 ----------------------------- end
// 自定义显示 ----------------------------- start
/*
7、自定义设置
*/
type: 'xxxx', // tip: 自定义与下面的对应
xxxx: {
template(data, sels) {
return `<div style="color: red;">${sels.length} / ${data.length}</div>`
},
},
// 自定义显示 ----------------------------- end
},
/*
8、【type 字段】展示类型
默认下拉显示 'absolute';
直接显示模式:'relative';
浮动布局:'fixed';
*/
type: 'absolute',
},
}
【示例】
(默认)方块显示方式
方块形状,隐藏删除图标
方块形状,超过一个隐藏
文字形状,简单拼接形式
自定义显示 label & template 选项
自定义显示 HTML(在上面示例基础上)
直接显示下拉 即:下拉展示在页面中。
iconfont
【说明】自定义选中图标
【类型】{object}
【值】目前仅配置 label 即可
- select 键:{string} 选中图标;
- unselect 键:{string} 非选中图标;
- half 键:{string} 半选图标;
- parent 键:{string} 父节点图标,值为 hidden 时,隐藏。
show
【说明】展开下拉的回调
【类型】{function}
【注意】回调先执行,再有展开交互。
hide
【说明】隐藏下拉的回调
【类型】{function}
【注意】回调先执行,再有关闭交互。
template
【说明】自定义渲染选项
【类型】{function}
callback({item, sels, name, value})
on
【说明】监听选中变化
【类型】{function}
callback({arr, change, isAdd})
- arr: 当前多选已选中的数据;
- change: 此次选择变化的数据,数组;
- isAdd: 此次操作是否是新增选项;
【返回】可以 return 一个数组,代表想选中的数据。
max
【说明】设置多选选中上限
【类型】{int}
【默认值】0 (即没有选中上限)
maxMethod
【说明】达到选中上限的回调
【类型】{function}
callback(sels, item)
- sels: 已选中数据;
- item: 当前选中的值;
name
【说明】表单提交时的 name
【类型】{string}
‘select’
layVerify
【说明】表单验证,同 layui 的 lay-verify
【类型】{string}
【默认值】‘’
layVerType
【说明】表单验证,同 layui 的 lay-verType
【类型】{string}
【默认值】‘’
layReqText
【说明】表单验证,同 layui 的 reqText
【类型】{string}
【默认值】‘’
toolbar
【说明】工具条
【类型】{object}
【默认值】-
- show 键:{boolean} 是否展示工具条 (true/false(def))
- showIcon 键: {boolean} 是否显示工具图标 (true(def)/false)
- list 键:{array} 工具条数组(默认有 ALL/全选,CLEAR/清空,REVERSE/反选,自定义,默认值 [‘ALL’, ‘CLEAR’])
【自定义】
list: [
'ALL',
'CLEAR',
{
// 显示图标,可以是 layui 内置的图标,也可以是自己引入的图标
// 传入的 icon 会转化为 <i class="layui-icon layui-icon-face-smile"></i>
icon: 'layui-icon layui-icon-face-smile',
name: 'xxx', // 显示名称
method: function (data) {
// data: 当前页面的数据
},
},
]
showCount
【说明】展示在下拉框中的最多选项数量
【类型】{int}
【默认值】0
enableKeyboard
【说明】是否启用键盘操作选项
【类型】{boolean}
【可选值】true/false
【默认值】true
enableHoverFirst
【说明】是否默认选中第一项
【类型】{boolean}
【可选值】true/false
【默认值】true
selectedKeyCode
【说明】选中的键盘 KeyCode
【类型】{int}
【可选值】全部 KeyCode
【默认值】13
autoRow
【说明】是否开启自动换行(选项过多时)
【类型】{boolean}
【可选值】true/false
【默认值】false
size
【说明】尺寸
【类型】{string}
【可选值】large/medium/small/mini
【默认值】medium
disabled
【说明】是否禁用多选
【类型】{boolean}
【可选值】true/false
【默认值】false
create
【说明】创建条目
【类型】{function}
callback(val, arr)
- val: 搜索的数据;
- arr: 搜索后的当前页面数据;
内部 return {object}
- name: 子项名称;
- value: 子项值;
【默认值】null
tree
【说明】树形结构
【类型】{object}
tree: {
show: false, // {boolean} 是否展示为树状结构 false(def)
showFolderIcon: true, // {boolean} 是否显示节点前的三角图标 true(true)
showLine: true, // {boolean} 是否显示虚线 true(def)
indent: 20, // {int} 间距
expandedKeys: [], // {array|boolean} 默认展开的节点数组,为 true 时展开所有所有节点
strict: true, // {boolean} 是否遵循严格父子结构 true(def)
simple: false, // {boolean} 是否开启极简模式
/*
{string} 标注节点类型的 key
leaf: 叶子节点;
parent: 父节点
half: 半选节点;
*/
nodeType: '__node_type',
/*
{boolean}
点击节点是否展开。
false: 时点击三角箭头进行展开操作;
true(def): 点击节点展开;
*/
clickExpand: true,
/*
{boolean}
点击节点是否选中。
false:只能点击复选框进行选中操作。
true: 点击节点任一地方都可选中。
*/
clickCheck: true,
}
cascader
【说明】级联结构
【类型】{object}
submitConversion
【说明】配置表单提交数据
【类型】{function}
callback(sels, prop)
- sels: 已选中数据;
- prop: 自定义的 prop;
done
【说明】渲染完成回调
【类型】{function}
全局方法
.render()
/**
* @brief: 渲染下拉选
* @param {object} options 上面的配置项
* @return {object} ins 实例对象
*/
const ins = xmSelect.render(options)
.get()
/**
* @brief: 获取页面中已经渲染的多选实例 (集合|数组)
* @param {string} filter:过滤el
* @param {object} single:是否返回单实例
* @return {array|object} insArr 符合条件的实例数组
*/
const insArr = xmSelect.get(filter, single)
xmSelect.get('#demo1') // 指定某一个获取
xmSelect.get(/demo.*/) // 正则获取
xmSelect.get(function (el) {
return el == '#demo1' || el == '#demo2'
})
// 返回 单实例 对象
xmSelect.get('#demo2', true)
.batch()
/**
* @brief: 批量操作已渲染的多选
* @param {string} filter:过滤el
* '': 空字符表示操作所有当前页面的多选。
* 正则:操作匹配的正则选择器;
* @param {object} method:需要执行的方法
* @param {any} args:执行方法的参数
* @return {array} insArr 符合条件的实例数组
*/
const insArr = xmSelect.batch(filter, method, ...args)
// 批量执行禁用
xmSelect.batch(/.*demo/, 'update', {
disabled: true,
})
// 批量执行 warning
xmSelect.batch(/.*demo/, 'warning', '#F00', true)
.arr2tree()
/**
* @brief: 把列表数据转化为树状结构
* @param {array} arr 数据
* @param {string} pid 父节点 id 的 key
* @param {string} id 对应 key
* @param {string} children 对应 key
* @param {string} topParentId 顶级节点的 id
* @return {*}
*/
xmSelect.att2tree(arr, pid, id, children, topParentId)
实例方法
xmSelect.render() 后会返回一个 xmSelect 对象,可以进行方法调用。(即上面返回的 ins)
.getValue()
/**
* @brief: 获取当前选中的数据
* @param {string} type
* name:
* nameStr:
* value:
* valueStr:
* @return {*}
*/
ins.getValue(type)
.setValue()
/**
* @brief: 动态设置数据
* @param {array} array 选中的数据
* @param {boolean} show 是否展开下拉
* 不传:默认当前显示状态;
* 取值:true/false
* @param {boolean} listenOn 是否触发on的监听,true/false(def)
* @return {*}
*/
ins.setValue(array, show, listenOn)
.append()
/**
* @brief: 追加赋值
* @param {array} array 追加的数据
* @return {*}
*/
ins.append(array)
.delete()
/**
* @brief: 删除赋值
* @param {array} array 删除的数据
* @return {*}
*/
ins.delete()
.opened()
/**
* @brief: 主动展开下拉
* @return {*}
*/
ins.opened()
.closed()
/**
* @brief: 主动关闭下拉
* @return {*}
*/
ins.closed()
.reset()
/**
* @brief: 重置为上一次的 render 状态
* @return {*}
*/
ins.reset()
.update()
/**
* @brief: 更新多选选中,reset 不保留
* @param {object} options 见配置项
* disabled键:
* true 启用
* false 禁用
* @return {*}
*/
ins.update(options)
.warning()
/**
* @brief: 警告
* @param {string} color 默认同 theme.maxColor
* @param {boolean} sustain 是否持续显示
* @return {*}
*/
ins.warning(color, sustain)
.getTreeValue()
/**
* @brief: 树节点模式下获取数据,v1.2.0 新增
* @param {boolean} leafOnly 是否只是叶子节点,默认值为 false
* @param {boolean} includeHalfChecked 是否包含半选节点,默认值为 false
* @return {*}
*/
ins.getTreeValue(leafOnly, includeHalfChecked)
.changeExpandedKeys()
/**
* @brief: 树模式下更新节点展开状态,v1.2.0新增
* @param {boolean|array} keys
* true: 全部展开;
* false: 全部关闭;
* 数组:展开的节点值;
* @return {*}
*/
ins.changeExpandedKeys(keys)
.enable()
/**
* @brief: 启用选项
* 即 disabled=false v1.2.0 新增
* @param {array} array 想要启用的选项数组
* @return {*}
*/
ins.enable(array)
.disable()
/**
* @brief: 禁用选项
* 即 disabled=true v1.2.0 新增
* @param {array} array 想要禁用的选项数组
* @return {*}
*/
ins.disable(array)
.calcPosition()
/**
* @brief: fixed 布局模式下重新计算位置 v1.2.2 新增
* @return {*}
*/
ins.calcPosition(array)
5、示例
基础使用
【特殊】只需要引入 xm-select.js,剩下的就只有渲染。
语言
默认选中
方法 1:默认选中:data 子项 selected: true
方法 2: initValue 配置项
修改提示
修改 选项-提示文字
修改 空数据-提示文字
修改 搜索-提示文字
搜索模式
下拉方向
自定义样式
分页
启用分页
自定义分页数
搜索 + 分页
分页无数据时不展示分页
远程分页
搜索 + 远程分页
单选
开启单选
单选完关闭下拉
更换显示方式 以单纯文本(而不是默认的选中项)显示
重复选
开启重复选
重复选 后关闭
更换显示方式(统计重复选的总数量) tip: 只能增不能减?有待完善
自定义属性
【场景】数据库返回的 子项字段 并不是 name 和 value,也许你提交的时候不止 name 和 value,怎么办?自定义就行。
自定义属性
主题
显示与隐藏
主动打开/关闭下拉框 (见文件内操作注释)
监听打开/关闭下拉框
显示方式
(默认)方块显示方式
方块形状,隐藏删除图标
方块形状,超过一个隐藏
文字形状,简单拼接形式
自定义显示 label & template 选项
自定义显示 HTML(在上面示例基础上)
直接显示下拉 即:下拉展示在页面中。
渲染相关
监听选择
实时监听
监听 + 动态赋值
实例:实现 2 个选项的选择为互斥。(即 A 选中,就去 B 选中;B 选中就去 A 选中。)
性能测试
渲染不同条数据
特殊:龙图腾电脑上,测试 10000 条数据时,选后,滑动选择每个间隔 接近 1s 才能被选中。
结果:分页是好使的。
多选上限
工具条
选项显示数量
【场景】当数量过大时,又不想使用分页的形式,就可以控制显示数量,用搜索的方式把最适合的数据展示出来。
【注意 1】此处与分页配置互斥,开启分页后,此配置无效。
【注意 2】使用此配置时建议开启搜索模式,否则无法显示全部数据。
分组
【核心】data 内 children 字段。
children 模式
分组的点击事件见里面详细说明。
带分页的分组
自动换行
【场景】当需要选择很多选项时,横向滚动满足不了你的需求,可以开启自动换行。
开启换行
layui 风格
隐藏图标
隐藏单项图标
隐藏多选图标:见上。
尺寸
警告
d1 主动触发默认警告
d2 自定义闪烁颜色(见上)
d3 持续显示(见上)
禁用
创建条目
关联 api
搜索不存在,则创建条目
注意:创建后的选项添加到多选选中,但下拉选中不添加。
单选创建 效果类似上面。
6、进阶示例
赋值
取值
表单提交
1)默认表单提交;
【规则】默认 xm-select 在 layui 的 form 中可以直接提交,默认的 name 值是 select
。
2) 修改 name 表单验证;
(在上面 demo 基础上)修改 name 表单验证
结果:上面的 name 属性对应的值被修改掉。
表格中多选
远程搜索
将搜索中示例。
动态数据
1)本地数据动态赋值;
2)远程数据动态赋值;
3)动态创建 xm-select 多选;
弹框中的多选
获取实例对象
关联 api .get(filter, single)
获取下拉选实例
批量操作
关联 api .batch(filter, single)
批量操作已渲染实例
7、扩展进阶
下拉自定义
下拉表格
更多:发挥想象力。
下拉树 Tree
下拉日期多选
下拉折叠面板
级联模式
8、常见问题
-1、formSelects 与 xm-select
formSelects 是作者很久以前开发的一款多选插件,在 jq 时代还是相对比较稳定,不过性能上有很大的问题。
痛并思痛后,开始学习其他开源组件的编写方案,最后决定重新开发。
xm-select 作者精心二次开发的组件, 在 formSelects 的样式基础上进行了性能优化。目前看来还是比较稳定的 _
-2、哪里下载
Gitee 码云下载, 使用时引入 xm-select.js 即可, 已经内置了 css
-3、为什么多选不显示
重要的事情说三遍, 需要(调用 api)渲染, 需要渲染, 需要渲染
-4、渲染后还是不显示
打开控制台查看是否报错;
加群: 660408068, 询问;
-5、ES6 语法
注意兼容性。