无value属性因其仅为语义分组容器,不参与表单提交;规范禁止设置value,浏览器忽略且JS读取为空;需用data-group等绑定至获取分组信息。

本身不携带可提交的值,它只是视觉和语义上的分组容器;真正能被表单提交或通过 JavaScript 获取的,只有 元素的 value 或 text。
为什么 没有 value 属性
HTML 规范明确禁止给 设置 value。浏览器会忽略该属性,JS 读取 element.value 也始终返回空字符串。它的唯一合法属性是 label(用于显示分组名)和 disabled(禁用整个分组)。
- 试图写
是无效的,不会被解析为数据源 - 表单序列化(如
new FormData(form)或form.serialize())完全跳过 - 如果需要“分组标识”,必须显式绑定到每个
上(例如用data-group)
获取选中项时如何同时拿到分组信息
不能靠 自身取值,但可以通过 DOM 层级关系反查:先获取选中的 ,再用 .parentElement 找到它的 ,读取其 label。
const select = document.querySelector('select');
select.addEventListener('change', () => {
const option = select.selectedOptions[0];
if (!option) return;
const optgroup = option.parentElement;
const groupLabel = optgroup && optgroup.tagName === 'OPTGROUP'
? optgroup.label
: '(no group)';
console.log('选中值:', option.value);
console.log('所属分组:', groupLabel);
});
- 注意判断
option.parentElement是否真是—— 顶级的父元素是 - 不要用
option.parentNode,某些情况下可能是 DocumentFragment(如动态插入) - 若需支持多选,遍历
select.selectedOptions并对每个做同样处理
想让分组也参与数据建模?用 data-* 绑定到
更可靠的做法是把分组语义“下沉”到每个选项,避免依赖 DOM 结构。例如:
立即学习“前端免费学习笔记(深入)”;
- 这样无论选项怎么移动、是否在
内,option.dataset.group始终可用 - 提交前可统一收集:
Array.from(select.selectedOptions).map(o => ({ value: o.value, group: o.dataset.group })) - 比靠 DOM 层级更稳定,也方便服务端直接解析
真正容易被忽略的是:分组的语义价值只存在于渲染和可访问性(如屏幕阅读器会读出 label),它不是数据载体。所有业务逻辑需要的分组标识,必须显式落到 节点上,否则运行时就丢了。











