先记住这个答案
<datalist> 包含候选 <option>,通过 id 与 <input list> 关联。用户输入时,浏览器可展示匹配建议;选中后,选项的 value 进入输入框。它不会把值限制在候选中,用户还可以自行输入。需要固定选项且不允许其他值时,用 <select> 更合适。候选弹层的具体外观与辅助技术支持由浏览器决定,不能假定所有环境完全一致。
list指向<datalist>的id<option>的value是填入输入框的值- 用户可输入候选列表之外的内容
- 候选弹层的样式与辅助技术支持有限
城市输入框怎么连起来
假设配送表单希望提示几个常用城市,但仍允许用户填写其他城市。<input> 保留自由文本能力,<datalist> 只提供提示。两者靠 list 与 id 的同一个值连接,不是靠相邻位置或共同的 name。
<label for='city'>城市</label>
<input id='city' name='city' list='city-options' />
<datalist id='city-options'>
<option value='北京'></option>
<option value='上海'></option>
<option value='深圳'></option>
</datalist>用户选中北京后,表单提交的是输入框 name 对应的当前值;<datalist> 自身不是一个额外的表单字段。用户输入杭州,即使列表里没有它,仍可保留并提交,除非输入框另有类型、模式等验证约束。不要用候选列表冒充白名单验证,服务端仍需检查业务允许的值。
与 select 和浏览器自动填充的区别
<select> 的选项是控件本身的选择范围,适合国家代码、固定状态等封闭集合。<datalist> 则服务于输入框,适合开放集合里的常见建议,例如城市、标签或已有项目名。autocomplete 属性控制浏览器如何使用历史输入或用户资料自动填充;list 指向作者在页面里提供的候选,来源和目的不同。
<option> 的 value 是进入输入框的值,label 或文本可能作为辅助显示信息,但不同浏览器呈现方式不一致。不要把必须让用户看到的解释只放在标签里,也不要依赖候选弹层承载复杂布局。若产品需要远程搜索、丰富的分组内容或精确的键盘交互,原生候选可能不够,需要专门设计并测试组件。
适配与无障碍检查
候选弹层的样式控制很有限,有些浏览器与屏幕阅读器组合不会完整播报候选内容。交付前用键盘、缩放和目标辅助技术实际试用,确认用户即使无法使用候选弹层,仍能直接输入并提交。输入框还应有清晰的 <label>,不能把候选项当作唯一说明。
list 并非适用于所有输入类型,具体呈现也可能不同。文本类输入通常最容易预测;例如范围输入可能把候选显示成刻度,而不是下拉选项。选择控件时先看用户要完成什么任务,再验证目标浏览器的行为,而不是只因为某个属性可写就认为体验相同。
容易答错的地方
- 以为候选之外的值会被拒绝
<datalist>提供建议,不定义封闭集合。只要输入值符合<input>本身的约束,用户就可以提交列表外的内容。需要固定集合时改用<select>或明确的验证逻辑。- 以为 datalist 会单独提交一个字段
- 真正的表单控件是
<input>。<datalist>提供候选,不因拥有id就成为提交字段;表单项的键通常来自输入框的name。
面试官还会怎么问?
选项有 label,提交的是 label 还是 value?
填入输入框的是 <option> 的 value,最终提交的也是输入框当前值。label 或文本只影响候选的辅助显示,具体显示方式可能随浏览器变化。
可以用 JavaScript 动态更新候选吗?
可以增删 <datalist> 里的 <option>。但远程联想要考虑请求时序、加载反馈和输入法体验;复杂场景还应测试键盘与辅助技术行为。
为什么输入框已经有 autocomplete,还要 list?
autocomplete 主要告诉浏览器如何处理自动填充;list 给出这个页面作者指定的候选。两者可以并存,但用户看到的建议来源和控制程度不同。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。