揭秘CSDN复制弹出登录框原理及解决方案

在日常搜索技术文章时,我们常常会遇到在CSDN上复制代码需要登录的情况。今天,我们就来深入探讨一下CSDN设置复制弹出登录框的原理,以及如何绕过这一限制实现代码的自由复制。

CSDN设置复制弹出登录框的原理

监听复制事件

CSDN主要通过JavaScript来监听页面的复制事件(copy事件)。当用户尝试复制页面上的内容时,就会触发预先设定好的事件处理函数,在这个函数中会弹出登录框。以下是示例代码:

javascript 复制代码
document.addEventListener('copy', function (event) {
    // 弹出登录框的逻辑
    // 例如:显示登录模态框等操作
});

在这段代码中,document.addEventListener('copy', ...) 用于监听整个文档的复制事件。一旦用户执行复制操作,就会执行回调函数,在回调函数里可以编写弹出登录框的具体逻辑,比如显示一个模态框要求用户登录。

设置CSS样式

除了监听复制事件,CSDN还会通过设置CSS样式来间接限制用户复制。例如,使用 user-select: none 样式禁止用户选中页面上的文本,从而达到限制复制的目的。示例代码如下:

sql 复制代码
pre, code {
    user-select: none;
}

这段CSS代码将 precode 标签内的文本设置为不可选中,这样用户就无法直接复制这些代码内容了。

解决方案代码分析(把这段脚本添加至油猴就行啦)

下面我们来看一段解决CSDN复制弹出登录框问题的代码,它通过几个步骤实现了代码的自由复制。

ini 复制代码
// ==UserScript==
// @name         CSDN免登录复制
// @namespace    http://tampermonkey.net/CSDN_
// @version      2025-04-23
// @description  CSDN免登录代码复制,优化复制功能和用户体验
// @author       JensenHuang
// @match        https://blog.csdn.net/*/article/details/*
// @icon         https://g.csdnimg.cn/static/logo/favicon32.ico
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    function addCss(code, id) {
        const style = document.createElement("style");
        const css = document.createTextNode(code);
        style.setAttribute("data-id", id || "codebox-css");
        style.appendChild(css);
        document.head.appendChild(style);
    }
    function copyCodeCssFunc() {
        const css = `    #content_views pre,    #content_views pre code {      -webkit-touch-callout: auto !important;      -webkit-user-select: auto !important;      -khtml-user-select: auto !important;      -moz-user-select: auto !important;      -ms-user-select: auto !important;      user-select: auto !important;    }`;
        addCss(css);
    }
    function copyCodeFunc() {
        copyCodeCssFunc();
        // 内容区
        var content_views = document.querySelector("#content_views");
        content_views.replaceWith(content_views.cloneNode(true));
       修改复制按钮,支持一键复制
        const buttons = document.querySelectorAll(".hljs-button");
        buttons.forEach((btn) => {
            // 更改标题
            btn.dataset.title = "复制";
            // 移除点击事件
            btn.setAttribute("onclick", "");
            // 克隆按钮
            var elClone = btn.cloneNode(true);
            // 替回按钮
            btn.parentNode.replaceChild(elClone, btn);
            // 重新添加点击事件
            elClone.addEventListener("click", (e) => {
                // 实现复制
                const target = e.target;
                const parentPreBlock = target.closest("pre");
                const codeBlock = parentPreBlock.querySelector("code");
                navigator.clipboard.writeText(codeBlock.innerText);
                console.log(codeBlock.innerText);
                target.dataset.title = "复制成功";
                setTimeout(() => {
                    target.dataset.title = "复制";
                }, 1000);
                e.stopPropagation();
                e.preventDefault();
            });
        });
    }
    copyCodeFunc();
})();

具体步骤分析

修改CSS样式

通过 copyCodeCssFunc 函数,将代码块的 user-select 样式设置为 auto,使代码块可以被选中和复制。在 copyCodeCssFunc 函数中,定义了一段CSS代码,将 #content_views 下的 prepre code 标签的 user-select 属性设置为 auto,并通过 addCss 函数将这段CSS代码添加到文档的头部。这样,代码块就可以被正常选中了。

克隆复制按钮并重新绑定事件

遍历所有的复制按钮,移除原有的点击事件,克隆按钮并替换原按钮,然后重新绑定点击事件。在新的点击事件处理函数中,使用 navigator.clipboard.writeText 方法将代码块的内容复制到剪贴板,并显示复制成功的提示。具体来说,首先使用 document.querySelectorAll('.hljs-button') 获取所有的复制按钮,然后对每个按钮进行处理。移除原有的点击事件后,克隆按钮并替换原按钮,再为新按钮添加点击事件。在点击事件处理函数中,通过 navigator.clipboard.writeText 方法将代码块的内容复制到剪贴板,并将按钮的标题设置为"复制成功",1秒后再恢复为"复制"。

阻止事件传播和默认行为

在点击事件处理函数中,调用 e.stopPropagation() 阻止事件冒泡,调用 e.preventDefault() 阻止默认行为,确保复制操作不会触发其他不必要的事件。这样可以避免复制操作引发其他意外的事件,保证复制功能的正常运行。

通过以上分析,我们了解了CSDN设置复制弹出登录框的原理,以及如何通过代码绕过这一限制。希望这篇文章能帮助你在浏览CSDN文章时更加方便地复制代码。

相关推荐
用户63879947730534 分钟前
每组件(Per-Component)与集中式(Centralized)i18n
前端·javascript
SsunmdayKT34 分钟前
React + Ts eslint配置
前端
开始学java37 分钟前
useEffect 空依赖 + 定时器 = 闭包陷阱?count 永远停在 1 的坑我踩透了
前端
zerosrat37 分钟前
从零实现 React Native(2): 跨平台支持
前端·react native
狗哥哥38 分钟前
🔥 Vue 3 项目深度优化之旅:从 787KB 到极致性能
前端·vue.js
青莲84339 分钟前
RecyclerView 完全指南
android·前端·面试
青莲84339 分钟前
Android WebView 混合开发完整指南
android·前端·面试
GIS之路43 分钟前
GDAL 实现矢量数据转换处理(全)
前端
大厂技术总监下海44 分钟前
Rust的“一发逆转弹”:Dioxus 如何用一套代码横扫 Web、桌面、移动与后端?
前端·rust·开源
加洛斯44 分钟前
SpringSecurity入门篇(2):替换登录页与config配置
前端·后端