可笑!在网页上复制点东西 还需要掏钱?教你copy事件的禁用

前言

哈喽 大家好!

我是木易巷,我回来啦!!!

现在好多平台都变成了不开会员不能复制这样的情况。士可杀不可辱!作为一个优秀的复制粘贴工程师,在网页上复制点东西,还需要我掏钱?

今天木易巷给大家讲解一下怎样使用代码写出这种效果,并且分享给大家几个方法来实现破解,可以直接看视频哦~

 

 

 

正文

这里有一个非常简单的页面,是由一些文本构成的,我们在浏览器上打开,是肯定可以随意复制的,我们没有做一些处理,所以是没有什么问题的。

 

 

那么我们如何使用代码来实现禁用复制呢?

首先呢,我们需要去监听一个事件,叫做【copy】,当复制发生的时候,它就会触发这个事件的运行,而我们要做的其实就是禁用事件的默认行为。

 

 

不仅如此,我们好像还可以干点什么!

比如说当在进行复制的时候,给他复制一些其他的东西。我们修改代码,现在代码修改过后,复制在粘贴就会粘贴到我们设置的这一句:「创作不易,请点个赞再来复制!」

再比如说在进行复制的时候,给一个弹框提示。

现在我们修改代码,这个弹框提示呢,我们在复制这个行为发生的时候,自动提示:「若有问题,请联系木易巷!」

 

 

这样呢,我们就设置就完成了。

解决方法

好,我们知道了这个原理之后,再来回过头来看这个问题,怎样去破解这个禁用复制呢?

我们打开浏览器的调试控制台,然后找到事件监听器,将copy给移除掉就完事啦!

 

 

如果感觉这样去浏览器去找相关的代码,再删除掉,比较麻烦。那这里木易巷给大家推荐几个浏览器插件,大家通过浏览器扩展下载插件,然后就可以自动实现这种效果,不用在每一次就要去修改一下网页的源码啦!

插件名称:

1、网页万能复制

2、超级复制(Super Copy)

OK,本期的分享就到这里!

 

 

2024-01-10 11:15:25【出处】:https://zhuanlan.zhihu.com/p/622850658

=======================================================================================

如何让网页中的copy事件失效?

当我想在网页复制点内容,ctrl + c 时被要求告知需要加入vip,需要登陆,完了还得在我复制得内容后面随意拉屎。对于这样的流氓行为,我不想惯着它了,搞它。搞它前,先要知道,网页是怎么知道我复制内容了的?


js是运行在浏览器的唯一脚本语言,为了实现网页与用户的各种交互行为,实现了n多事件,最为常见的比如click点击事件。这些众多事件中,就有一个copy事件,用来监听用户的复制行为,比如执行ctrl + c 或是 右键复制。


现在知道了copy,那要阻止流氓行为,只要让网页中的copy事件失效就可以了。问题是,怎么才能让它失效?到这里,先搞清楚网页是如何绑定一个事件的?

一般来说绑定事件有 **三种常见形式**:
1.使用on+事件名称直接绑定
2.使用addEventListener函数绑定
3.使用行内属性进行绑定

第一种事件绑定:使用on+事件名称直接绑定

该如何处理,先来一段代码:
  1. <body>
  2. <div class="copy-box">
  3. <p>text content</p>
  4. </div>
  5. </body>
上述代码中,得到一个这样的结构:body -> div.copy-box -> p。

我们分别在div.copy-box 、document、window上绑定一个click事件,如下:
  1. const ev = 'onclick'
  2. document.querySelector('.copy-box')[ev] = () => console.log('dom event: ' + ev)
  3. document[ev] = () => console.log('document event: ' + ev)
  4. window[ev] = () => console.log('window event: ' + ev)
根据js的事件冒泡机制,事件会从实际触发的节点依次向上冒泡。在上述代码里,window对象包含了整个网页的所有内容。document对象就是文档对象,包含了网页了所有节点信息,document也是window下的一个对象。根据包含关系得到以下结构:window -> document -> html ->body -> div.copy-box -> p。所以在上述代码执行时,会依次输出dom event: onclick、document event: onclick、window event: onclick。

敏锐一点,可以发现,事件的绑定都是在各自的最后出现[ev],ev是一个变量,值是:onclick。在不使用变量的情况下, 就是onclick。这就是js 对象数据类型的经典使用方式。

[ev] === .onclick. 这样完全可以把上述代码中的document.querySelector('.copy-box')、document、window看成对象结构,onclick就是这个对象中的某一个键,后面运行的函数就是值。既然是对象,那么是不是只要让这个对象的键onclick不被修改就可以了。是的, 想要锁定对象的值不能被修改,就得寄出 Object.defineProperty。

defineProperty的基本语法:Object.defineProperty(对象, 键, {value[2], writable[3], enumerable[4]、configurable[5]})

要实现禁止对象的属性值被修改,只需关注writable[6] 即可,得到以下代码:
  1. const o = { value: null, writable: false }
  2. Object.defineProperty(HTMLElement.prototype, ev, o)
  3. Object.defineProperty(Document.prototype, ev, o)
  4. Object.defineProperty(window, ev, o)
让这段代码放在事件绑定之前运行,在页面再次点击div.copy-box,会发现绑定的事件不会在触发,达到了禁止的目的。

第二种事件绑定:使用addEventListener函数绑定。

  1. const ev = 'click'
  2. document.querySelector('.copy-box').addEventListener(ev, () => console.log('dom event: ' + ev))
  3. document.addEventListener(ev, () => console.log('document event: ' + ev))
  4. window.addEventListener(ev, () => console.log('window event: ' + ev))
我们发现,这时的事件绑定都使用了addEventListener函数,事件通过函数参数进行绑定,没有了之前的类似对象的键值关系,之前的禁止代码对于addEventListener失去了作用。但是,addEventListener是函数,那是不是可以提前篡改这个函数?
  1. HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
  2. Document.prototype._addEventListener = Document.prototype.addEventListener;
  3. Window.prototype._addEventListener = Window.prototype.addEventListener;
  4. HTMLElement.prototype.addEventListener = _xaddEventListener;
  5. Document.prototype.addEventListener = _xaddEventListener;
  6. Window.prototype.addEventListener = _xaddEventListener;
  7. function _xaddEventListener(a, b, c) {
  8. if (a != ev) this._addEventListener(a, b, c);
  9. };
这段代码中,我们在各自的原型链找到addEventListener,同时写一个自定义的_addEventListener函数,先将原本的addEventListener赋值给它。接着开始篡改原始addEventListener 。
函数,篡改的函数里对传入的事件进行判断,识别到click,直接丢弃不在处理。这是再次点击div.copy-box,会发现绑定的事件也不会在触发了,再次达到了禁止的目的。

第三种事件绑定:使用行内属性进行绑定。

  1. // html
  2. html -> onclick="clickfn('html')"
  3. body -> onclick="clickfn('body')"
  4. div -> onclick="clickfn('dom')"
上述代码中,我们在div、body、html处分别绑定了click事件。要达到事件失效,只需要干掉这个onclick属性即可。
  1. window.addEventListener('DOMContentLoaded', function() {
  2. const clicks = [...document.querySelectorAll('[' + onev + ']')]
  3. clicks.forEach(item => {
  4. item.removeAttribute(onev)
  5. item.removeAttribute(onev)
  6. })
  7. })
备注:DOMContentLoaded
MDN 的解释:当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。

上述代码里,我们将逻辑处理放到了事件DOMContentLoaded里运行,为了干掉所有的onclick属性,使用document.querySelectorAll来搜索。循环移除。
至此,事件的禁止就ok了。

贴上一份完整代码:
  1. const ev = 'copy'
  2. const onev = 'on' + ev
  3. const o = { value: null, writable: false }
  4. Object.defineProperty(HTMLElement.prototype, onev, o)
  5. Object.defineProperty(Document.prototype, onev, o)
  6. Object.defineProperty(window, onev, o)
  7. HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
  8. Document.prototype._addEventListener = Document.prototype.addEventListener;
  9. Window.prototype._addEventListener = Window.prototype.addEventListener;
  10. HTMLElement.prototype.addEventListener = _xaddEventListener;
  11. Document.prototype.addEventListener = _xaddEventListener;
  12. Window.prototype.addEventListener = _xaddEventListener;
  13. function _xaddEventListener(a, b, c) {
  14. if (a != ev) this._addEventListener(a, b, c);
  15. };
  16. window.addEventListener('DOMContentLoaded', function() {
  17. const clicks = [...document.querySelectorAll('[' + onev + ']')]
  18. clicks.forEach(item => {
  19. item.removeAttribute(onev)
  20. item.removeAttribute(onev)
  21. })
  22. })
这么让它在所有网页运行,**篡改猴** 你值得拥有。
  1. // ==UserScript==
  2. // @name 移除所有网页绑定的copy函数,实现自由复制
  3. // @version 1.0
  4. // @description try to take over the world!
  5. // @author -
  6. // @match *://*/*
  7. // @icon https://g.csdnimg.cn/static/logo/favicon32.ico
  8. // @grant none
  9. // @run-at document-start
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13. // 上述完整代码放这
  14. })();

 

出处:https://www.duidaima.com/Group/Topic/jQuery/17823

=======================================================================================

个人使用

根据上面的思想,试了一下,发现并不行,还是无法复制,于是想到还是使用removeEventListener方法看看能否找到突破口,还真找到了,如下:

document.querySelector(".jbcode").removeEventListener("copy",getEventListeners(document.querySelector(".jbcode"))["copy"][0].listener)

但是,对于使用addEventListener绑定的匿名函数,无法移除,还有就是getEventListeners只在控制台中有效,不是标准函数

不过看网上,还是给出了很多的方法,我自己进行修改了一下,如下:

// ==UserScript==
// @name         doCopy
// @namespace    http://tampermonkey.net/
// @version      0.2.3
// @description  解决csdn登录后才能复制、优化“关注阅读更多”功能、去除复制后的copyright小尾巴
// @author       Jack
// @match        *blog.csdn.net/*
// @match        http*://*.csdn.net/*
// @match        http*://www.jb51.net/*
// @grant        none
// @require      https://cdn.bootcss.com/jquery/2.2.1/jquery.min.js
// @run-at       document-end
// ==/UserScript==


(function (){
    'use strict';

    doCopy();

    // Your code here...
    $(document).ready(function(){
        // 在此处执行希望在页面加载完成后执行的操作
        //setTimeout(doCopy,1000);

    });

})();

function doCopy()
{

    var host = window.location.host;

    //恢复csdn.net网站上代码的复制功能
    if(host=="blog.csdn.net")
    {
        //优化登陆后复制
        $('code').css({'user-select':'unset'})
        $('#content_views').css({'user-select':'unset'})
        $('#content_views pre').css({'user-select':'unset'})

        //移除“登陆后复制”按钮
        $('.hljs-button').remove();
        //移除readmore按钮,并显示全文
        $('#article_content').css({'height':'initial'});
        $('.hide-article-box').remove();
        //隐藏自动显示登录框
        //$(".passport-login-container").css({'display':'none'});
        $(".passport-login-container").remove();
        //移除头部固定的作者信息
        $(".column_info_box").remove();


        //去除复制后的copyright小尾巴
        document.querySelectorAll('*').forEach(item=>{
            item.oncopy = function(e) {
                e.stopPropagation();
            }
        });
    }

    //恢复jb51.net网站上代码的复制功能
    if(host=="www.jb51.net")
    {
        $('div .jb51code').css({'user-select':'unset'});
        $("div .codetool").remove();
        console.log("===========")
        window.addEventListener('copy', function(e){e.stopPropagation();
                                                   e.stopImmediatePropagation();}, true)
        //移除复制事件
        $("div.jb51code").each((ind,ele) => {
            //var han=getEventListeners(ele);
            //var han2=ele.getEventListeners2();
            //var l=han["copy"][0].listener;
            //debugger;
            //ele.removeEventListener("copy",getEventListeners(ele)["copy"][0].listener);
            //ele.removeEventListener("copy",function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)});
            //ele.unbind('copy');
            //console.log(ele.getEventListeners(ele))
        });
    }
    //else
    {
        const ev = 'copy'
        const onev = 'on' + ev
        const o = { value: null, writable: false }
        Object.defineProperty(HTMLElement.prototype, onev, o)
        Object.defineProperty(Document.prototype, onev, o)
        Object.defineProperty(window, onev, o)
        HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
        Document.prototype._addEventListener = Document.prototype.addEventListener;
        Window.prototype._addEventListener = Window.prototype.addEventListener;
        HTMLElement.prototype.addEventListener = _xaddEventListener;
        Document.prototype.addEventListener = _xaddEventListener;
        Window.prototype.addEventListener = _xaddEventListener;
        function _xaddEventListener(a, b, c) {
            if (a != ev) this._addEventListener(a, b, c);
        };
        window.addEventListener('DOMContentLoaded', function() {
            const clicks = [...document.querySelectorAll('[' + onev + ']')]
            clicks.forEach(item => {
                item.removeAttribute(onev)
                item.removeAttribute(onev)
            })
        })
    }
}
View Code

 

// ==UserScript==
// @name         doCopy
// @namespace    http://tampermonkey.net/
// @version      0.2.3
// @description  解决csdn登录后才能复制、优化“关注阅读更多”功能、去除复制后的copyright小尾巴
// @author       Jack
// @match        *blog.csdn.net/*
// @match        http*://*.csdn.net/*
// @match        http*://www.jb51.net/*
// @grant        none
// @require      https://cdn.bootcss.com/jquery/2.2.1/jquery.min.js
// @run-at       document-end
// ==/UserScript==


(function (){
    'use strict';

    doCopy();

    // Your code here...
    $(document).ready(function(){
        // 在此处执行希望在页面加载完成后执行的操作
        //setTimeout(doCopy,1000);

    });

})();

function doCopy()
{
    var host = window.location.host;

    //恢复csdn.net网站上代码的复制功能
    if(host=="blog.csdn.net")
    {
        //优化登陆后复制
        $('code').css({'user-select':'unset'})
        $('#content_views').css({'user-select':'unset'})
        $('#content_views pre').css({'user-select':'unset'})

        //移除“登陆后复制”按钮
        $('.hljs-button').remove();
        //移除readmore按钮,并显示全文
        $('#article_content').css({'height':'initial'});
        $('.hide-article-box').remove();
        //隐藏自动显示登录框
        $(".passport-login-container").remove();
        $(".passport-login-container").css({'display':'none'});
        //移除登录提示框
        $(".passport-login-tip-container false").remove();
        $(".passport-login-tip-container false").css({'display':'none'});
        //移除头部固定的作者信息
        $(".column_info_box").remove();


        //去除复制后的copyright小尾巴
        document.querySelectorAll('*').forEach(item=>{
            item.oncopy = function(e) {
                e.stopPropagation();
            }
        });

        console.log("=====[doCopy end : blog.csdn.net]=====")
    }

    //恢复jb51.net网站上代码的复制功能
    if(host=="www.jb51.net")
    {
        $('div .jb51code').css({'user-select':'unset'});
        $("div .codetool").remove();
        window.addEventListener('copy', function(e){e.stopPropagation();
                                                   e.stopImmediatePropagation();}, true)
        //移除复制事件
        $("div.jb51code").each((ind,ele) => {
            //var han=getEventListeners(ele);
            //var han2=ele.getEventListeners2();
            //var l=han["copy"][0].listener;
            //debugger;
            //ele.removeEventListener("copy",getEventListeners(ele)["copy"][0].listener);
            //ele.removeEventListener("copy",function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)});
            //ele.unbind('copy');
            //console.log(ele.getEventListeners(ele))
        });

        console.log("=====[doCopy end: www.jb51.net]=====")
    }
    //else
    {
        const ev = 'copy'
        const onev = 'on' + ev
        const o = { value: null, writable: false }
        Object.defineProperty(HTMLElement.prototype, onev, o)
        Object.defineProperty(Document.prototype, onev, o)
        Object.defineProperty(window, onev, o)
        HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
        Document.prototype._addEventListener = Document.prototype.addEventListener;
        Window.prototype._addEventListener = Window.prototype.addEventListener;
        HTMLElement.prototype.addEventListener = _xaddEventListener;
        Document.prototype.addEventListener = _xaddEventListener;
        Window.prototype.addEventListener = _xaddEventListener;
        function _xaddEventListener(a, b, c) {
            if (a != ev) this._addEventListener(a, b, c);
        };
        window.addEventListener('DOMContentLoaded', function() {
            const clicks = [...document.querySelectorAll('[' + onev + ']')]
            clicks.forEach(item => {
                item.removeAttribute(onev)
                item.removeAttribute(onev)
            })
        })
    }
}
View Code

 

v0.24:

// ==UserScript==
// @name         doCopy
// @namespace    http://tampermonkey.net/
// @version      0.2.4
// @description  解决csdn登录后才能复制、优化“关注阅读更多”功能、去除复制后的copyright小尾巴
// @author       Jack
// @match        *blog.csdn.net/*
// @match        http*://*.csdn.net/*
// @match        http*://www.jb51.net/*
// @grant        none
// @require      https://cdn.bootcss.com/jquery/2.2.1/jquery.min.js
// @run-at       document-end
// ==/UserScript==


(function (){
    'use strict';

    doCopy();

    // Your code here...
    $(document).ready(function(){
        // 在此处执行希望在页面加载完成后执行的操作
        //setTimeout(doCopy,1000);

    });

})();

function doCopy()
{
    var host = window.location.host;

    //恢复csdn.net网站上代码的复制功能
    if(host=="blog.csdn.net")
    {
        //优化登陆后复制
        $('code').css({'user-select':'unset'})
        $('#content_views').css({'user-select':'unset'})
        $('#content_views pre').css({'user-select':'unset'})

        //移除“登陆后复制”按钮
        $('.hljs-button').remove();
        //移除readmore按钮,并显示全文
        $('#article_content').css({'height':'initial'});
        $('.hide-article-box').remove();
        $('main div.blog-content-box pre').css({'max-height':'none'});

        //隐藏自动显示登录框
        $(".passport-login-container").remove();
        $(".passport-login-container").css({'display':'none'});
        //移除登录提示框
        $(".passport-login-tip-container false").remove();
        $(".passport-login-tip-container false").css({'display':'none'});
        //移除头部固定的作者信息
        $(".column_info_box").remove();


        //去除复制后的copyright小尾巴
        document.querySelectorAll('*').forEach(item=>{
            item.oncopy = function(e) {
                e.stopPropagation();
            }
        });

        console.log("=====[doCopy end : blog.csdn.net]=====")
    }

    //恢复jb51.net网站上代码的复制功能
    if(host=="www.jb51.net")
    {
        $('div .jb51code').css({'user-select':'unset'});
        $("div .codetool").remove();
        window.addEventListener('copy', function(e){e.stopPropagation();
                                                   e.stopImmediatePropagation();}, true)
        //移除复制事件
        $("div.jb51code").each((ind,ele) => {
            //var han=getEventListeners(ele);
            //var han2=ele.getEventListeners2();
            //var l=han["copy"][0].listener;
            //debugger;
            //ele.removeEventListener("copy",getEventListeners(ele)["copy"][0].listener);
            //ele.removeEventListener("copy",function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)});
            //ele.unbind('copy');
            //console.log(ele.getEventListeners(ele))
        });

        console.log("=====[doCopy end: www.jb51.net]=====")
    }
    //else
    {
        const ev = 'copy'
        const onev = 'on' + ev
        const o = { value: null, writable: false }
        Object.defineProperty(HTMLElement.prototype, onev, o)
        Object.defineProperty(Document.prototype, onev, o)
        Object.defineProperty(window, onev, o)
        HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
        Document.prototype._addEventListener = Document.prototype.addEventListener;
        Window.prototype._addEventListener = Window.prototype.addEventListener;
        HTMLElement.prototype.addEventListener = _xaddEventListener;
        Document.prototype.addEventListener = _xaddEventListener;
        Window.prototype.addEventListener = _xaddEventListener;
        function _xaddEventListener(a, b, c) {
            if (a != ev) this._addEventListener(a, b, c);
        };
        window.addEventListener('DOMContentLoaded', function() {
            const clicks = [...document.querySelectorAll('[' + onev + ']')]
            clicks.forEach(item => {
                item.removeAttribute(onev)
                item.removeAttribute(onev)
            })
        })
    }
}
View Code

 

 v0.25:增加对blog.51cto.com的copy功能

// ==UserScript==
// @name         doCopy
// @namespace    http://tampermonkey.net/
// @version      0.2.5
// @description  解决csdn登录后才能复制、优化“关注阅读更多”功能、去除复制后的copyright小尾巴
// @author       Jack
// @match        *blog.csdn.net/*
// @match        http*://*.csdn.net/*
// @match        http*://www.jb51.net/*
// @match        http*://blog.51cto.com/*
// @grant        none
// @require      https://cdn.bootcss.com/jquery/2.2.1/jquery.min.js
// @run-at       document-end
// ==/UserScript==


(function (){
    'use strict';

    doCopy();

    // Your code here...
    $(document).ready(function(){
        // 在此处执行希望在页面加载完成后执行的操作
        //setTimeout(doCopy,1000);

    });

})();

function doCopy()
{
    var host = window.location.host;

    //恢复csdn.net网站上代码的复制功能
    if(host=="blog.csdn.net")
    {
        //优化登陆后复制
        $('code').css({'user-select':'unset'})
        $('#content_views').css({'user-select':'unset'})
        $('#content_views pre').css({'user-select':'unset'})

        //移除“登陆后复制”按钮
        $('.hljs-button').remove();
        //移除readmore按钮,并显示全文
        $('#article_content').css({'height':'initial'});
        $('.hide-article-box').remove();
        $('main div.blog-content-box pre').css({'max-height':'none'});

        //隐藏自动显示登录框
        $(".passport-login-container").remove();
        $(".passport-login-container").css({'display':'none'});
        //移除登录提示框
        $(".passport-login-tip-container false").remove();
        $(".passport-login-tip-container false").css({'display':'none'});
        //移除头部固定的作者信息
        $(".column_info_box").remove();


        //去除复制后的copyright小尾巴
        document.querySelectorAll('*').forEach(item=>{
            item.oncopy = function(e) {
                e.stopPropagation();
            }
        });

        console.log("=====[doCopy end : blog.csdn.net]=====")
    }

    //恢复blog.51cto.com网站上代码的复制功能
    if(host=="blog.51cto.com")
    {
        window.addEventListener('copy', function(e){e.stopPropagation();e.stopImmediatePropagation();}, true)
        window.addEventListener('keydown', function(e){e.stopPropagation();e.stopImmediatePropagation();}, true)
        window.addEventListener('keyup', function(e){e.stopPropagation();e.stopImmediatePropagation();}, true)
        console.log("=====[doCopy end: blog.51cto.com]=====")
    }

    //恢复jb51.net网站上代码的复制功能
    if(host=="www.jb51.net")
    {
        $('div .jb51code').css({'user-select':'unset'});
        $("div .codetool").remove();
        window.addEventListener('copy', function(e){e.stopPropagation();
                                                   e.stopImmediatePropagation();}, true)
        //移除复制事件
        $("div.jb51code").each((ind,ele) => {
            //var han=getEventListeners(ele);
            //var han2=ele.getEventListeners2();
            //var l=han["copy"][0].listener;
            //debugger;
            //ele.removeEventListener("copy",getEventListeners(ele)["copy"][0].listener);
            //ele.removeEventListener("copy",function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)});
            //ele.unbind('copy');
            //console.log(ele.getEventListeners(ele))
        });

        console.log("=====[doCopy end: www.jb51.net]=====")
    }
    //else
    {
        const ev = 'copy'
        const onev = 'on' + ev
        const o = { value: null, writable: false }
        Object.defineProperty(HTMLElement.prototype, onev, o)
        Object.defineProperty(Document.prototype, onev, o)
        Object.defineProperty(window, onev, o)
        HTMLElement.prototype._addEventListener = Element.prototype.addEventListener;
        Document.prototype._addEventListener = Document.prototype.addEventListener;
        Window.prototype._addEventListener = Window.prototype.addEventListener;
        HTMLElement.prototype.addEventListener = _xaddEventListener;
        Document.prototype.addEventListener = _xaddEventListener;
        Window.prototype.addEventListener = _xaddEventListener;
        function _xaddEventListener(a, b, c) {
            if (a != ev) this._addEventListener(a, b, c);
        };
        window.addEventListener('DOMContentLoaded', function() {
            const clicks = [...document.querySelectorAll('[' + onev + ']')]
            clicks.forEach(item => {
                item.removeAttribute(onev)
                item.removeAttribute(onev)
            })
        })
    }
}
View Code

 

 

 

 

需要的自行拿去。

=======================================================================================

如何查看html元素绑定的事件

在baidu中输入以上标题,baidu的AI自动生成的,如下:

要查看HTML元素绑定的事件,可以使用JavaScript来获取。

  1. 首先,需要通过选择器或者直接引用DOM对象来获取到目标HTML元素。比如,我们想要查看id为"myElement"的元素上绑定的事件,可以这样写:

var element = document.getElementById("myElement");
  1. 然后,可以使用getEventListeners()函数来获取该元素上所有已经注册的事件处理程序。示例如下:

var eventHandlers = getEventListeners(element);
console.log(eventHandlers); // 输出包含了该元素上所有事件及其相关信息的对象
  1. getEventListeners()返回的结果是一个对象,键名表示事件类型(比如click、mouseover等),值则是一个数组,每个元素都是一个事件处理程序的详细信息。

  2. 最后,根据自己的需求进行进一步操作,比如打印特定事件的处理程序、修改事件处理程序等。

希望能帮助到你!

提示:AI自动生成,仅供参考

 

 

 

出处:https://www.baidu.com/s?wd=%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8Bhtml%E5%85%83%E7%B4%A0%E7%BB%91%E5%AE%9A%E7%9A%84%E4%BA%8B%E4%BB%B6&rsv_spt=1&rsv_iqid=0xf86c0210000077e0&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&oq=%25E5%25A6%2582%25E4%25BD%2595%25E6%259F%25A5%25E7%259C%258Bhtml%25E5%2585%2583%25E7%25B4%25A0%25E7%259A%2584%25E4%25BA%258B%25E4%25BB%25B6&rsv_btype=t&inputT=3958&rsv_t=7708cz6ERTybRYJ0E3wYrpZhhrBX%2B2MrkeGmXDz37L0Ar8oo9IY3S2D%2B%2BPMiipoiM3pr&rsv_pq=bf22bdac000b6682&sug=%25E5%25A6%2582%25E4%25BD%2595&rsv_sug3=45&rsv_sug2=0&rsv_sug4=4872

=======================================================================================

如何在 JS 文件中(非控制台)使用 getEventListeners 函数?

提问区

经测试 getEventListeners 函数仅能在控制台中使用而不能在 JS 文件或油猴脚本当中使用。

由于很多网站对用户复制事件进行了监听,一旦检测到用户复制内容,就会在复制内容末尾处加一段「转载表明出处」的信息,还会把原有复制的图文信息转换为纯文本信息。很烦躁,于是想用油猴脚本试图移除所有复制监听事件。

欲使用 removeEventListener 必须先知道事件侦听器是什么。我并不知道因此只能遍历每个 DOM 元素找到监听了 copy 事件的元素。经查阅资料得知有一个 getEventListeners 函数可以找到。于是写了一个像这样的代码:

[...document.all].forEach(i => {
    if (getEventListeners(i).copy)
        i.removeEventListener("copy", getEventListeners(i).copy[0].listener);
});

放到一个新的油猴脚本中,并对某些网站生效。

结果运行后报错说 getEventListeners 未定义,改成 window.getEventListeners 后还是未定义。理由大概说是 getEventListeners 这个函数和 $、$$ 等类似只能在浏览器控制台当中使用。

那么如何在油猴脚本中解决这个问题?不必考虑兼容性,因为只是自用。

 

评论区

  1. “你不让我好过我也不让你过,都他妈的别过了”大法,干掉其他全局 API

比如,它这个页面的 copy 事件回调里用到了 window.getSelection() 来获取你选中的节点,那你就直接把这个 API 干掉,window.getSelection = null。它的函数一执行就报错,自然不可能执行到修改剪切板内容的地方。当然,得确保这个不会影响页面的其他你所需要的功能,如果单单是个报错,就让他们的程序员看报错监控后苦思冥想吧。

你甚至可以覆盖原型链上的 addEventListener 不让 copy 事件绑定。

2. “谁起步早谁抢占制高点”大法,MutationObserver

比如页面里是给 .article-content 这个元素绑定的 copy 事件,那就想办法在它的 addEventListener() 执行前就就绑上自己的事件处理函数,在函数里执行 e.stopImmediatePropagation() 这样它自己的回调函数就不会触发了。具体难点就是怎么能比页面更快执行 addEventListener,那就尝试用 MutationObserver 实时监听页面所增加的节点,不过由于它的回调也是异步触发的,所以这个方法也不一定能行。

3. “高级程序降维打击一般程序员”大法,事件捕获

一般程序员绑定事件都不加 addEventListener 的第三个参数,或者传 false,这是事件冒泡阶段才触发的,你可以在事件传递更早的阶段,捕获阶段的第一个节点上,也就是 window 上绑定处理函数,不用管它是给具体哪个节点绑了 copy,通杀:

window.addEventListener('copy', function(e){e.stopPropagation();e.stopImmediatePropagation();}, true)

你甚至可以在页面 load 事件后再执行这行代码 ,不慌不忙拿捏他。

发布于 2022-03-08 14:40
 

 

7 人赞同了该回答

js万物皆可覆盖,只要优先级够高。

只需要在html开头植入一段代码,确保它最先执行就可操控全局。例如

HTMLElement.protype.addEvenListener=function(){

}

这么做的话,全局的dom添加的事件都会失效(dom里的属性onxxxx=无效,它不是调用addEvenListrner添加的事件),因为所有元素都继承自HTMLElement,就像java所有对象都继承自java.lang.Object,根据这个特性,你就可以劫持所有后面添加的监听事件,就可以适当的不触发

发布于 2022-03-08 15:01 
 
 
4 人赞同了该回答

考虑对addEventListener做劫持试试看?

let oldadd=EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener=function (...args){
console.log('addEventListener',...args)
oldadd.call(this,...args)
}

发布于 2022-03-08 16:39
 

 
3 人赞同了该回答

直接干掉ClipboardEvent.clipboardData的set不是更轻松么

发布于 2022-03-08 16:58

 

出处:https://www.zhihu.com/question/520181485/answer/2379752368

 

这个文章让我看的,只能说评论区都是人才!!!

其实技术重要,但更重要的是想法!~

哈哈!~

=======================================================================================

js 获取元素绑定事件的列表 chrome getEventListeners、 Events-EventListenerList 、$._data(a[0], 'events').click[0].handler

技术上有什么办法获得指定 HTMLElement 上有绑定那些 #JavaScript 函数事件,及其处理函数么?

比如我有一个按钮,想知道他绑定了那些事件? click 事件的处理函数是什么?

elem.onclick 这种只能绑定唯一的一个事件处理函数,可以直接取到。

DOM Level 3 有 [http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-EventListenerList eventListenerList] 接口,但是现在还没有浏览器实现。

不过可以通过框架包装的方式获取列表。 另外 Google Chrome 浏览器的开发者工具有提供查看元素绑定了哪些事件的特性, 猜测是通过解析页面及其引入的 JavaScript 源码得到的 (据我所知,Firebug 的性能分析就是通过 inject 代码到各个函数中来实现的)。

延伸阅读

  • http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-EventListenerList
  • http://www.quirksmode.org/js/events_advanced.html

Chrome浏览器方法:getEventListeners

在控制台的listener中,只能显示函数的第一行,如果你写的函数是多行的,那就需要把命令打全了:

getEventListeners(document.getElementById("btn1")).click[0].listener

console会把函数的全部都打印出来。

jQuery读取事件列表的方法:

$(function(){

$("#atest1").click(function(e){

console.log("进入a链接跳转2");

location.href="http://www.baidu.com/?t="+new Date().getTime();

console.log("a链接跳转已经执行3");

});

setTimeout(function(){

document.addEventListener('click', function(e){

console.log("document事件捕获开始1");

// 通知浏览器不要执行与事件关联的默认动作。

// e.preventDefault();

 

console.log(e.toElement);

//控制台执行有效

//getEventListeners($("a#atest1").get(0)).click[0].remove();

 

// 显示当前目标元素的绑定事件有哪些

var a=$(e.toElement);

var p = $._data(a[0], 'events').click[0].handler;

 

if(p.toString().indexOf("location")>0){

 $._data(a[0], 'events').click[0].handler=function(){}

}

$.get("http://www.raodaor.com/test/tag.ashx?stm=1464233065021", function(){

console.log("ajax");

if(p.toString().indexOf("location")>0){

$._data(a[0], 'events').click[0].handler=p();

}

});

}, true);

},1000);

});

 

出处:http://camnpr.com/javascript/2264.html

=======================================================================================

JQuery事件机制

事件机制#

事件委托#

注册事件有以下几种方式:

  1. 简单事件绑定:$("div").click(function(){})
  2. bind事件绑定:$("div").bind("click mouseenter",function(){})
  3. delegate事件绑定
  4. on事件绑定(推荐)

delegate#

delegate:委托,给父元素注册委托事件,最终还是由子元素执行。

它有三个参数:
• 第一个参数:事件最终由谁来执行
• 第二个参数:事件类型
• 第三个参数:函数

Copy
<button>增加</button>
<div>
  <span>111</span>
  <p>1</p>
  <p>2</p>
</div>
Copy
$(function () {
  $("button").click(function () {
    $("<p>111</p>").appendTo("div")
  })

  // delegate:只能注册委托事件
  $("div").delegate("p", "click", function () {
    alert("eee")
  })
})

 

on#

它有四个参数:

  1. 第一个参数:绑定事件的名称;
  2. 第二个参数:执行事件的后代元素(可选),如果没有后代元素,那么事件将由自己执行;
  3. 第三个参数:传递给处理函数的数据,事件触发的时候通过 event.data 来使用(不常使用);
  4. 第四个参数:事件处理函数;

注册简单事件:

Copy
$("p").on("click", function () {
  alert("heh1")
})

注册委托事件:

Copy
$("div").on("click", "p", function () {
  alert("heh1")
})

 

事件解绑#

事件解绑有三种方式,分别是unbind、undelegate、off。

Copy
// unbind方式
$(selector).unbind()    // 解绑所有事件
$(selector).unbind("click")    // 解绑指定事件

// undelegate方式
$(selector).undelegate()    // 解绑所有undelegate事件
$(selector).undelegate("click")    // 解绑所有click事件

// off方式
$(selector).off()    // 解绑所有事件
$(selector).off("click")    // 解绑所有click事件

 

触发事件#

.trigger():根据绑定到匹配元素的给定的事件类型执行所有的处理程序和行为。

Copy
$(selector).click()    // 触发click事件
$(selector).trigger("click")

 

出处:https://www.cnblogs.com/mq0036/p/17956155#1170291741
7 人赞同了该回答

js万物皆可覆盖,只要优先级够高。

只需要在html开头植入一段代码,确保它最先执行就可操控全局。例如

HTMLElement.protype.addEvenListener=function(){

}

这么做的话,全局的dom添加的事件都会失效(dom里的属性onxxxx=无效,它不是调用addEvenListrner添加的事件),因为所有元素都继承自HTMLElement,就像java所有对象都继承自java.lang.Object,根据这个特性,你就可以劫持所有后面添加的监听事件,就可以适当的不触发

发布于 2022-03-08 15:01
 

posted on 2024-01-10 11:18  jack_Meng  阅读(208)  评论(0编辑  收藏  举报

导航