selected属性仅在页面首次加载时生效,是布尔属性,写上即生效,不可赋值;多个option同时设置时仅第一个被选中;disabled的option加selected无效;SSR中必须服务端输出,否则触发水合错误。

selected 属性只在页面首次加载时生效
它不是运行时开关,也不是 JS 可随时“触发”的状态。浏览器解析 HTML 时,遇到带 selected 的 <option>,就把它设为初始选中项;一旦页面完成加载,这个属性就不再参与控制——后续 JS 改了 select.value 或 select.selectedIndex,selected 属性本身可能还留在 DOM 上,但已失去作用。
常见错误现象包括:
- HTML 里写了
<option value="sh" selected>上海</option>,但 JS 在DOMContentLoaded里又执行了select.value = "bj",结果默认还是北京 - Vue/React 中绑定了受控值,
selected完全被忽略,连调试都看不出问题 - 服务端渲染(SSR)时没输出
selected,客户端水合后出现 mismatch,控制台报错且界面闪动
selected 是布尔属性,别加等号或值
selected 是 HTML5 规范定义的布尔属性,写上即真,不写即假。它不需要、也不应该带任何值。
这些写法都是错的:
立即学习“前端免费学习笔记(深入)”;
<option value="sh" selected="true">上海</option><option value="sh" selected="selected">上海</option><option value="sh" selected="">上海</option>
正确写法只有一种:<option value="sh" selected>上海</option>。多一个字符都是冗余,部分校验工具会警告,某些老旧解析器甚至可能误判。
多个 option 同时写 selected,浏览器只认第一个
HTML 规范明确:当多个 <option> 带 selected,浏览器仅将第一个视为有效,默认选中它,其余忽略。这不是兼容性差异,是所有现代浏览器统一行为。
更麻烦的是 JS 层面的影响:
-
select.selectedIndex永远是0(第一个带selected的索引),哪怕你本意是想选第三个 -
select.selectedOptions.length永远是1,即使 DOM 上有多个selected属性 - 如果用 JS 动态遍历
option.selected === true,会得到多个true,但界面和表单提交值只反映第一个
所以务必确保:服务端/模板生成时,只给且仅给一个 <option> 加 selected。
disabled 的 option 加 selected 没效果
给禁用项加 selected,视觉上不会高亮,大多数浏览器也不会把它当作“已选中”处理——表单提交时该字段值仍为空,select.value 读出来也是空字符串或 undefined(取决于是否还有其他非禁用选项)。
典型误用场景:
-
<option value="" selected disabled>请选择</option>—— 看似稳妥,实则首次加载时下拉框显示空白(因为禁用项不能被选中) - 用户无法点击它,也无法通过键盘切换到它,但表单提交时却发了个空值
真正安全的占位写法是:<option value="" disabled>请选择</option> 不加 selected,再让下一个可用项(如 <option value="bj" selected>北京</option>)承担默认职责;或者用 required 配合前端校验,强制用户主动选择。
最易被忽略的一点:selected 和 select.value 是两套机制,前者只管初始渲染,后者管运行时状态。混用却不同步,是多数表单逻辑出错的根源。



















