data-*属性仅作静态标记,不可用于权限控制;它不被浏览器校验,易被篡改,必须配合后端鉴权与前端实时check()调用,仅在行为拦截中提取上下文信息。

data-* 属性不能做权限控制,只能做静态标记。你把它当开关用,等于把门锁画在门板上——看着像,推一下就开了。
为什么 data-permission="edit" 不能替代真实权限校验
浏览器不解析、不校验、不拦截任何 data-* 值;它只是字符串,存在 DOM 上就完事了。用户右键“检查元素”,改个 data-permission="admin",再点按钮,前端 JS 若只靠这个判断是否调接口,后端没拦住,就直接越权了。
- 后端未鉴权:API 接口没校验 JWT scope 或 RBAC 角色,
data-*再准也没用 - 前端没兜底:JS 没在点击前调用权限 SDK 校验
check("edit:product"),而是直接if (el.dataset.permission === "edit") { api.update() } - 数据已过期:用户权限被回收,但 HTML 是服务端渲染的静态页,
data-permission还是旧值,没人刷新它
data-* 在权限系统里唯一靠谱的用法
它只该出现在「前端行为拦截」环节,且仅作为上下文提取器,不是决策依据。
- 给操作按钮加
data-action="delete"和data-resource-id="prod_789",供统一权限拦截函数快速拿到意图和目标 - 表格行写
data-resource-type="order",配合事件委托,在父容器 click 监听中提取并传给canUser("delete", type, id) - 配合
contenteditable="false"锁字段,但必须用beforeinput事件二次拦截粘贴/Backspace(2026年6月起所有主流浏览器已支持)
dataset 读取时最常踩的三个坑
dataset 看似方便,但类型、命名、同步性全是雷区。
-
data-is-pending="false"→el.dataset.isPending是字符串"false",不是布尔值;别写if (el.dataset.isPending),要写el.dataset.isPending === "true" -
data-user-id="123"→ 正确读法是el.dataset.userId;写成data-userId或data-UserID,DOM 根本不认,dataset.userId返回undefined - 动态改权限状态?别直接
el.dataset.permission = "view";这不会触发重新校验逻辑,也不会更新 UI 状态 —— 它只是改了个字符串,而真实权限状态在内存或 API 响应里
真正难的不是怎么写 data-permission,而是怎么让每个按钮点击前都经过一次 check() 调用,并确保这个调用能拿到最新权限快照。dataset 只负责把「这个按钮想干啥、对谁干」拎出来,剩下的事,它一概不管。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











