如何在jQuery中对select选项排序并保留各选项的data属性值
问题根源
- jQuery的
.data()API只会操作jQuery内部维护的缓存数据,不会同步更新DOM上的data-*原生属性。如果你后续是通过原生getAttribute、或其他不读取jQuery缓存的方式获取data-*属性,拿到的永远是初始值。 - 你当前的实现逻辑是覆写原有option元素的属性,而非直接替换排序后的option节点。且
$(o).data(对象)的行为是合并新旧数据,而非清空原有缓存后写入新数据,会导致旧的data值残留。 - 部分场景下如果
datafields中存在大写驼峰的key(比如DOM上的data-user-id,jQuery读出来会自动转成userId),直接写入.data()不会反向把驼峰key转成中划线格式的DOM属性,也是值不匹配的常见原因。
修复方案
直接重构逻辑,排序后替换所有option节点,完全避免缓存和覆写的问题,修复后的代码如下:
sortSelectOptions: function (options){ // 提取所有option的完整数据 var arr = options.map(function (_, o) { const $o = $(o); return { t: $o.text(), v: o.value, d: $o.data(), s: $o.is(':selected'), // 可按需扩展其他需要保留的属性,比如disabled、class等 disabled: o.disabled, className: o.className }; }).get(); // 按文本排序,用localeCompare代替字符串直接比较,兼容中文和特殊字符 arr.sort(function (o1, o2) { return o1.t.localeCompare(o2.t); }); // 清空原有option,插入新的排序后的节点 const $select = options.parent(); options.remove(); // 移除旧节点同时清除关联的jQuery缓存 arr.forEach(function(item) { const $newOpt = $('<option></option>') .val(item.v) .text(item.t) .prop('selected', item.s) .prop('disabled', item.disabled) .addClass(item.className); // 如果需要同步DOM上的data-*原生属性,保留下面这段循环即可 Object.keys(item.d).forEach(key => { // 驼峰转中划线,匹配原生data属性的命名规则 const attrKey = 'data-' + key.replace(/([A-Z])/g, '-$1').toLowerCase(); $newOpt.attr(attrKey, item.d[key]); }); $select.append($newOpt); }); }
如果你不需要同步DOM上的
data-*原生属性,仅需要通过jQuery的.data()方法能读到正确值,可以删掉上述代码中的attr循环,直接用$newOpt.data(item.d)写入数据即可,性能更好。
内容的提问来源于stack exchange,提问作者pape04
相关产品推荐
相关产品推荐

