前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库data-* 自定义属性 JavaScript
HTML语义与文档

data-* 适合存什么?屏幕阅读器会读出来吗?

data-* 适合给元素附上少量页面内部数据,例如 data-user-id,脚本可从 element.dataset.userId 读取。它本身不提供可访问名称,屏幕阅读器通常不会把属性值当内容朗读;也不要把需要保密的数据放进 HTML 属性。

前端进阶之旅 · 一题精讲更新于 2026.09.29
HTML#语义与文档
先看核心答案读代码示例
理解线索

元素上的轻量数据通道

  1. data-*把自定义键值写在 HTML 元素上
  2. dataset用 JavaScript 属性读写对应字符串
  3. 无障碍语义需要可读名称时使用文本、标签或合适的 ARIA 属性

浏览器中的任何人都能查看元素属性,data-* 不是隐私或权限边界。

核心回答

先记住这个答案

data-* 是给 HTML 元素附加自定义数据的标准方式,适合少量与当前元素有关、供脚本或样式使用的值。data-user-id 可用 element.dataset.userId 读取,得到字符串。它不会自动变成可见文本、表单提交值或元素的无障碍名称;屏幕阅读器通常不会仅因存在这个属性就朗读其值。公开在 DOM 中的属性也不适合存密钥、令牌或敏感个人信息。

  • data-* 保存元素相关的自定义数据
  • data-* 可通过 dataset 读取
  • dataset 读到的是字符串
  • 属性值不自动成为无障碍名称

给列表项带一个内部标识

事件委托常需要知道点击的是哪条记录。可以把记录 ID 写在对应元素的 data-* 属性里,让事件处理器从目标附近的元素读出来。这个 ID 只是客户端定位线索,服务端仍应验证访问权限,不能因为 HTML 里有某个数字就信任该请求。

从属性读写 datasetHTML
<button class='user-row' data-user-id='42'>
  查看用户
</button>
<script>
  const button = document.querySelector('.user-row')
  console.log(button.dataset.userId) // 字符串 42
  button.dataset.userId = '43' // 同步更新 data-user-id
</script>

属性名中的连字符在 dataset 中转为驼峰形式:data-user-id 对应 userId。用 dataset 写入数字或布尔值时,也会转成字符串;需要数字时自行解析,并处理空值或非法输入。属性值能在开发者工具里直接看到,因此它只是数据传递方式,不是安全存储。

屏幕阅读器会不会读

单独写 data-tooltip,不会自动为按钮提供可访问名称。需要让用户知道按钮作用,优先放可见文字;图标按钮可用合适的 aria-label 或关联文本。不要把关键说明仅藏在 data-* 里,否则依赖辅助技术的用户可能得不到信息。

也不应把 data-* 当成 ARIA 属性的别名。aria-expanded 描述控件的展开状态,浏览器和辅助技术有约定的语义;data-expanded 则只是作者自定义字符串。组件可以两者同时写,一个供样式或脚本,一个表达无障碍状态,但必须保持值同步。CSS 能用属性选择器读取 data-* 来切换外观,却不会替你补上语义。

与其他存储方式怎么分工

只和某个 DOM 元素相关的轻量标识、测试钩子或样式状态,data-* 很方便。较复杂的业务状态通常放在 JavaScript 状态层,避免把大对象序列化进属性并在 DOM 与脚本中维护两份。需要随表单提交的值,应使用表单控件及其 name,不能假设 data-* 会被浏览器自动提交。

用户可见的内容应写成文本节点或语义元素。若信息会随着交互变化,更新可见文字及相应的无障碍状态,比只修改 dataset 更可靠。把所有数据都塞进 data-*,不仅难维护,还会把本应明确的内容和状态藏起来。

回答前,多想一步

容易答错的地方

说 dataset.userId 自动是数字
HTML 属性都是文本,dataset 读到的也是字符串。字符串 42 与数字 42 在严格比较下不同。要算术运算或发需要数字的请求,应明确转换并校验。
说屏幕阅读器绝对不可能接触 data-*
属性本身不提供语义,也不会自动成为可访问名称。但脚本可以把它复制到可见文本或 ARIA 属性中,某些样式生成内容的处理也有环境差异。准确说法是不要依赖 data-* 本身传达关键无障碍信息。
试着用自己的话回答

面试官还会怎么问?

data-user-id 和普通 id 有什么不同?

id 是文档内元素标识,供锚点、标签关联和选择器等使用,应该在文档中唯一。data-user-id 是作者定义的业务数据,可以在多处元素上出现同一个用户 ID。

写了 data-price,表单提交时会自动带上吗?

不会。浏览器的表单数据来自符合条件的表单控件及其 name,不是任意元素的自定义属性。需要提交时应放进合适的控件或由脚本显式组装。

能把访问令牌放在 data-token 里给脚本读吗?

不应把需要保密的令牌放进 DOM。页面源码和开发者工具都能读到属性值;data-* 没有访问控制能力,暴露敏感数据的风险与写在普通 HTML 中相同。

从一道题,走向一组知识

把知识连起来

语义与文档

datalist 怎么给输入框加候选值?

data-* 可存页面内部提示,但 <datalist> 提供的是输入框的原生候选交互。

语义与文档

网站 favicon 要提供哪些文件,sizes 怎么写?

两题都涉及 HTML 属性;图标的 sizes 是浏览器定义的标准语义,不能换成 data-sizes。

参考资料

  • HTML:语义与文档参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 给列表项带一个内部标识
  3. 屏幕阅读器会不会读
  4. 与其他存储方式怎么分工
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑