您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
// ==UserScript==
当前为
// ==UserScript== // @name 星号密码框显示明文密码 // @namespace Violentmonkey Scripts // @match *://*/* // @grant none // @version 1.1 // @license MIT // @author - // @description // ==UserScript== // @name 星号密码框显示明文密码 // @namespace Violentmonkey Scripts // @match *://*/* // @grant none // @license MIT // @author - // @description # 密码可视交互功能说明 // // 本功能旨在提升用户在**输入或查看密码**时的交互体验。通过简单的 **鼠标悬停操作**,用户可临时查看密码框中的明文内容,从而增强使用的便捷性与准确性。 // // --- // // ## ✨ 功能亮点 // // ### 🔍 密码可见性切换 // - 用户将鼠标悬停在密码输入框上时,系统**自动切换为明文显示模式**; // - 鼠标移出后,自动恢复为密文状态; // - 无需点击额外按钮,显著提升交互效率。 // // ### 🔄 兼容动态页面与懒加载场景 // - 支持异步加载或动态渲染的页面(如 AJAX 请求加载、React/Vue 等前端框架组件); // - 确保在各类复杂前端架构中功能稳定运行。 // // ### ⚡ 轻量高效实现 // - 基于原生 JavaScript 实现,**不依赖任何第三方库**; // - 占用资源少,性能优异; // - 兼容主流浏览器:Chrome、Firefox、Edge 等。 // // ### 🔐 安全性保障 // - 显示密码仅限于客户端视觉呈现; // - 数据传输与存储仍保持加密状态; // - 不影响原有安全机制,保障用户信息安全。 // // --- // // ## 🛠️ 技术实现简述 // // ### 基础结构 // - 使用 HTML 中 `<input type="password">` 作为基础输入元素。 // // ### 核心逻辑 // - 监听 `mouseover` 和 `mouseout` 事件; // - 动态修改 `input.type` 属性,在 `"text"` 与 `"password"` 之间切换。 // // ### 动态兼容处理 // - 对于动态加载的内容: // - 可采用 **事件委托** 或 **MutationObserver** 检测 DOM 变化; // - 确保新加入的密码框也能正确绑定交互事件。 // // --- // // 该功能设计简洁实用,兼顾用户体验与安全性,适用于多种 Web 应用场景。 // ==/UserScript== (function() { 'use strict'; function bindPasswordEvents(input) { input.addEventListener('mouseenter', () => input.type = 'text'); input.addEventListener('mouseleave', () => input.type = 'password'); } function handleMutations(mutations) { debugger mutations.flatMap(e => [...e.addedNodes]).filter(node => node.nodeType === Node.ELEMENT_NODE).forEach(node => { if (node.tagName === 'INPUT' && node.type === 'password') { bindPasswordEvents(node); } else { // 检查其子节点 node.querySelectorAll('input[type="password"]').forEach(bindPasswordEvents); } }); // mutations.forEach(mutation => { // mutation.addedNodes.forEach(node => { // if (node.nodeType !== Node.ELEMENT_NODE) { // return; // } // if (node.tagName === 'INPUT' && node.type === 'password') { // bindPasswordEvents(node); // } else { // // 检查其子节点 // node.querySelectorAll('input[type="password"]').forEach(bindPasswordEvents); // } // }); // }); } const observer = new MutationObserver(handleMutations); const config = { childList: true, subtree: true }; observer.observe(document, config); // 初始化现有密码输入框的事件绑定 document.querySelectorAll('input[type="password"]').forEach(bindPasswordEvents); })(); // ==/UserScript== (function() { 'use strict'; function bindPasswordEvents(input) { input.addEventListener('mouseenter', () => input.type = 'text'); input.addEventListener('mouseleave', () => input.type = 'password'); } const observer = new MutationObserver((mutations)=>{ mutations.flatMap(e => [...e.addedNodes]).filter(node => node.nodeType === Node.ELEMENT_NODE).forEach(node => { if (node.tagName === 'INPUT' && node.type === 'password') { bindPasswordEvents(node); } else { node.querySelectorAll('input[type="password"]').forEach(bindPasswordEvents); } }); }); observer.observe(document, { childList: true, subtree: true }); // 初始化现有密码输入框的事件绑定 document.querySelectorAll('input[type="password"]').forEach(bindPasswordEvents); })();