如何为 Select2 下拉选项批量添加自定义 data-* 属性

本文介绍在初始化 select2 时,如何将 json 数据中的自定义字段(如 `s3_key`)直接映射为 `

Select2 默认支持通过 data 选项传入结构化数组(每个对象含 id、text 等字段),但原生不自动将额外字段(如 s3_key)渲染为 DOM 属性。若仅在 select2:select 或 change 事件中动态添加 data-* 属性,会导致初始选中项缺失该属性——这正是你遇到的问题:页面加载时已有默认值,但对应

✅ 正确解法是:在初始化前预处理数据,利用 Select2 的 templateResult 和 templateSelection 钩子 + 自定义 data 结构,或更简洁地——借助 option 元素的 dataset 特性,在渲染阶段注入属性。但最轻量、兼容性最佳的方式,是在 Select2 渲染完成后,遍历其内部生成的 (注意:不是操作 .select2-selection 的伪元素,而是原始

不过,更推荐以下零副作用、一次初始化即完成的方案:

✅ 推荐方案:初始化后立即同步 data 属性(安全可靠)

const $select = $('#id-gci-main');

// 假设 $aJsonGCIsPrincipalesOtorgados 已转为 JS 数组
const selectData = ;

$select.select2({
  language: '',
  closeOnSelect: true,
  allowClear: true,
  placeholder: '',
  data: selectData
});

// 关键:初始化后立即为所有 

⚠️ 注意事项

  • 不要操作 .select2-container 内部 DOM:Select2 的下拉列表是动态渲染的虚拟 DOM,直接修改它不稳定且易被覆盖。
  • 务必操作原始 :它们由 Select2 初始化时自动生成,且 data-* 属性会完整保留在原生元素上,后续 :selected 或 .find(':selected') 均可安全读取。
  • dataset 与 attr() 的区别:使用 .attr('data-s3_key', value) 可确保属性写入 HTML,.data('s3_key') 才能正确读取;若用 .data() 方法设置,仅存于 jQuery 缓存,不会反映在 HTML 属性中。
  • 服务端 JSON 输出需确保 id 类型一致:PHP 中 json_encode() 默认将整数 ID 转为数字,而 HTML value 属性始终为字符串,因此 option[value="1"] 匹配 id: 1 是安全的(jQuery 自动类型宽松匹配)。

? 进阶技巧:统一管理数据映射关系

若需频繁访问 s3_key,建议构建内存索引对象(如答案中所示),避免重复 DOM 查询:

// 初始化后构建映射表(O(1) 查找)
const s3KeyMap = selectData.reduce((map, item) => {
  map[item.id] = item.s3_key;
  return map;
}, {});

// 后续任意时刻获取:
const currentKey = s3KeyMap[$select.val()];

此方式性能更优,尤其适用于大数据集或高频调用场景。

综上,在 .select2() 初始化后立即遍历 selectData 并为对应