先记住这个答案
<datalist> 与 <input> 配合提供候选提示,不是强制选择。输入框的 list 指向数据列表的 id,浏览器可在用户输入时展示匹配建议;用户仍可输入列表之外的内容。表单提交时发送的是该输入框的当前值,后端不能把候选列表当成安全白名单。
list值指向<datalist>的id- 候选项只是建议,不是白名单
- 提交的是输入框当前值
- 严格枚举应使用选择控件或校验
列表如何连到输入框
例如城市搜索中常见城市可以预填候选,但还要允许输入其他城市。list 写在输入框上,值与 <datalist> 的 id 一致;列表中的 <option> 提供候选值。浏览器展示与过滤方式可能不同,不能靠某一种下拉面板外观判断是否关联成功。
<label for="city">城市</label>
<input id="city" name="city" list="cities">
<datalist id="cities">
<option value="北京"></option>
<option value="上海"></option>
</datalist>用户输入“广州”仍是合法的自由文本输入,即使它不在候选中。提交的数据项是 city=广州,而不是 <option> 的索引。若需要用稳定 ID 作为后端值,单靠 datalist 的显示文字不够,还须设计明确映射。
什么时候不要用建议列表
省份代码、角色权限或付费档位这类只能从固定集合中选的字段,用 <select> 通常更直接。若设计必须允许搜索式输入,也要在提交时核对结果是否在允许集合,并给出清晰错误提示。
required 只能阻止空值,不能保证值属于 <datalist> 候选;pattern 可以施加字符格式约束,但复杂枚举依然由业务规则决定。即使前端做了核对,服务端仍需验证收到的值。
datalist 的选项只是建议,用户仍可键入列表里没有的文本。比如城市输入框列了热门城市,用户输入一个冷门城市时,浏览器不会因为它不在 <option> 中就判无效。如果业务要求只能从固定集合选,提交时仍须验证,或者使用真正的 <select>。它也不适合直接替代复杂自动补全:无法统一控制候选项的排序、分组和键盘交互,视觉呈现还会随浏览器变化。
容易答错的地方
- 把
datalist当成带搜索的select - 前者允许自由输入,后者的选项范围由控件规定。两者的值域承诺不同。
- 用
required保证用户选了候选项 required只要求非空,不检查文本是否来自建议列表。
面试官还会怎么问?
datalist 自己会提交吗?
不会。关联它的输入框若有 name,该输入框的当前值才参与表单提交。
怎样只允许列表中的城市?
用 <select>,或在输入后对照允许集合并在服务端重复校验。
option 的显示文字与值不同怎么办?
实际写入输入框并提交的通常是候选的 value;应检查浏览器呈现方式,不把展示文字当稳定 ID。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。