tom-select使用drag-drop插件时如何保留拖拽自定义排序顺序
问题根因
tom-select 初始化时默认会对已选中的选项执行内置排序规则(默认按文本字母序排列),即使你已经把拖拽调整后的顺序存入数据库,只要初始化时没有显式指定已选项的渲染顺序,组件就会按默认规则重排已选值,导致自定义顺序丢失。
实现步骤
全程不需要修改拖拽插件的源码,只需要调整初始化配置和数据加载逻辑即可,同时可以保留下拉选项按字母排序的原有效果:
- 提前预处理加载数据
从后端拉取两类数据:全量下拉选项列表、当前字段已选中的值数组。注意已选值数组必须是数据库中存储的、按拖拽调整后的顺序排列的原始数组,不要在前端做任何排序处理。 - 调整初始化配置,禁用已选项自动排序
初始化时不要依赖原生select的selected属性自动识别已选值(原生option默认按字母序渲染,会打乱顺序),显式传入按自定义顺序排列的已选值数组,同时关闭组件全局默认排序,单独给下拉面板保留字母排序逻辑,参考配置:
// 实例化tom-select const selectIns = new TomSelect('#multi-select', { plugins: ['drag_drop'], // 保留原有拖拽插件 // 核心配置:关闭全局自动排序,已选项严格按传入的items顺序渲染 sortField: null, // 传入按自定义顺序排好的已选值数组 items: orderedSelectedValuesFromDB, // 传入全量下拉选项 options: allOptionsFromDB, // 单独给下拉面板的选项设置字母排序,不影响已选标签的顺序 onDropdownOpen: function() { const optionNodes = Array.from(this.dropdown_content.querySelectorAll('.option')) optionNodes.sort((prev, next) => prev.textContent.localeCompare(next.textContent)) optionNodes.forEach(node => this.dropdown_content.appendChild(node)) } })
- 校验拖拽后的顺序存储逻辑
确保拖拽调整顺序后,你存入数据库的是组件实例返回的原始顺序数组,不要做额外排序处理:
// 监听拖拽排序完成事件,拿到最新顺序存库 selectIns.on('drop', () => { const latestOrder = selectIns.items // 调用后端接口,将latestOrder原样存入数据库即可 }) // 新增选项时也同步更新顺序 selectIns.on('item_add', () => { const latestOrder = selectIns.items // 同步存库 })
避坑提示:不要在页面渲染时提前输出带selected属性的原生option标签,否则tom-select初始化时会优先读取DOM里的option顺序,覆盖你通过items配置传入的自定义顺序。
内容的提问来源于stack exchange,提问作者Artur79
相关产品推荐
相关产品推荐

