核心是动态修改input的type属性实现密码明文切换,浏览器原生支持password与text互切,无需第三方库;须避免直接操作value或contenteditable,切换后手动focus并防抖处理。

用 type="password" 和 type="text" 切换就能实现
核心就是动态改 <input> 的 type 属性,别想复杂。浏览器原生支持 type="text" 和 type="password" 互切,不需要任何第三方库或自定义输入框。
常见错误是直接操作 input.value 或用 contenteditable 模拟——这会导致密码明文残留、焦点丢失、移动端软键盘异常等问题。
- 必须用原生
<input type="password">初始化 - 切换时只改
el.type,不要删重建 DOM - 切换后手动调用
el.focus()保持焦点(尤其 Safari 下容易失焦) - 按钮图标建议用 Bootstrap 自带的
bi-eye/bi-eye-slash,别用纯文字 “显示/隐藏”
Bootstrap 5 的正确 HTML 结构长这样
重点在包裹容器加 class="input-group",密码框和按钮用 class="input-group-text" 对齐,否则在不同屏幕宽度下容易错位或被截断。
<div class="input-group mb-3">
<input type="password" class="form-control" id="passwordInput">
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
<i class="bi bi-eye-slash"></i>
</button>
</div>
注意:id="togglePassword" 要唯一;type="button" 必须写,否则在表单里点它会触发表单提交。
addEventListener 里怎么安全切换 type
不能无条件设 input.type = "text",因为部分老浏览器(如 IE11)不支持运行时改 type,会抛错;现代浏览器虽支持,但连续快速点击仍可能出问题。
- 先检查
input.type === "password"再决定切哪边 - 切换后立刻更新按钮图标:
icon.classList.toggle("bi-eye")、icon.classList.toggle("bi-eye-slash") - 加个简单防抖:300ms 内重复点击忽略,避免用户狂点导致状态错乱
- 移动端需监听
touchstart,不只是click(iOS Safari 对click有 300ms 延迟)
为什么不用 autocomplete="off" 或 readonly 来“增强安全”
加 autocomplete="off" 对密码显示/隐藏功能毫无帮助,反而可能干扰密码管理器识别字段;设 readonly 再 remove 是典型误区——它会让输入框无法获得焦点,且某些安卓键盘拒绝在 readonly 状态下弹出。
真正要注意的是:切换成 type="text" 后,密码就以明文形式存在于 DOM 中,如果页面被 XSS 注入,就有泄漏风险。所以生产环境别在敏感后台(如银行、支付)强推此功能,或者配合 onblur 自动切回 password。
最常被忽略的一点:密码框内容长度超过 20 字符时,显示状态下横向滚动条可能遮挡右侧按钮,要用 overflow-x: hidden + text-overflow: ellipsis 控制,而不是靠 JS 截断 value。


















