核心是动态修改input的type属性,在password和text间切换;须缓存value与光标位置、手动恢复并聚焦,同步更新aria-label与图标状态,避免失焦、光标错位及无障碍失效。

用 type="password" 和 type="text" 切换实现基础可见性控制
核心就是动态修改 <input> 元素的 type 属性。不能直接写死成 type="text",否则失去密码掩码保护;也不能只靠 CSS 遮盖(比如用 text-security),因为不兼容旧浏览器且无法真正“显示明文”。必须用 JS 切换原生 type 值。
注意:IE10+ 和所有现代浏览器都支持运行时修改 type,但 IE9 及更早版本会抛错 InvalidStateError —— 如果还需兼容 IE9,得用替代方案(如双 input + visibility 控制),但当前绝大多数项目可忽略。
实操建议:
- 初始
<input type="password">,确保默认安全 - 绑定点击事件到图标(如
<i class="eye-icon"></i>),不要绑在 label 或整个容器上,避免误触 - 切换时只改
input.type,**不要**同时改input.value或重设焦点(会导致光标跳到开头) - 切换后调用
input.focus()保持输入焦点,提升体验
图标状态同步:用 aria-label 和 class 控制视觉与可访问性
用户点击后,图标要立刻反映当前状态(比如“关闭眼”变“睁开眼”),否则交互意图模糊。纯靠 JS 切 class 是最轻量做法,但别忘了屏幕阅读器用户。
常见错误现象:图标变了,但 aria-label 没更新,读屏软件仍报“显示密码”,实际已隐藏。
实操建议:
- 初始图标加
aria-label="隐藏密码"(因默认是 password 类型) - 每次切换时同步更新:
icon.setAttribute('aria-label', isShowing ? '隐藏密码' : '显示密码') - 用 class 区分状态,例如
icon.classList.toggle('is-hidden'),CSS 里用.eye-icon.is-hidden::before { content: "?️" }和.eye-icon:not(.is-hidden)::before { content: "?" } - 避免用
display: none隐藏图标,改用visibility: hidden或透明度,保证 ARIA 属性仍可被读取
聚焦与光标位置异常:为什么输入框失焦或光标跑到开头?
典型表现:点图标后,输入框瞬间失去焦点,或者光标跳到最左边,用户继续打字时内容插在开头,很反直觉。
根本原因:某些浏览器(尤其是 Safari 和旧版 Chrome)在修改 type 时会重置 input 的内部状态,包括 selection(选区)和 focus 状态。
实操建议:
- 切换前缓存光标位置:
const pos = input.selectionStart - 切换后立即恢复:
input.setSelectionRange(pos, pos) - 再调用
input.focus()—— 注意顺序:先setSelectionRange,再focus(),否则 Safari 下无效 - 如果用了防抖或异步逻辑(比如等图标动画结束再切 type),务必把缓存和恢复逻辑放在同一帧内,避免被浏览器 layout 触发打断
移动端软键盘行为:iOS 上 type 切换可能触发键盘收起再弹出
iOS Safari 在 type 从 password 切到 text 时,有时会强制收起软键盘,哪怕 input 仍处于 focus 状态。用户得再点一次才能唤出键盘,体验断裂。
这不是 bug,而是 iOS 对敏感字段的主动干预。绕过它几乎不可能,但可以弱化影响。
实操建议:
- 不在
input失焦时才切 type,而是在用户点击图标时立即响应,减少等待感 - 给图标加
touch-action: manipulation,避免 iOS 300ms 延迟导致误判 - 不依赖
change或input事件监听 type 切换结果,它们不触发;只信click+ 主动查input.type - 如果项目对移动端体验要求极高,可考虑用
inputmode="text"配合自定义遮罩(如用<span></span>覆盖字符),但代价是放弃原生密码校验、复制粘贴限制等能力
selectionStart 和 iOS 键盘行为,上线前务必真机验证。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











