在页面显示到屏幕之前删除DOM元素(在Chrome扩展中) [英] Deleting DOM elements before the Page is displayed to the screen (in a Chrome extension)

查看:681
本文介绍了在页面显示到屏幕之前删除DOM元素(在Chrome扩展中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个扩展,在将页面显示到屏幕之前,将删除某些页面元素(通过id或class)。我试着用DOMContentLoaded作为事件在文档上使用事件侦听器,但似乎在页面显示给用户后执行javascript,然后将其删除,因此它不像我想要的那样流畅(不显示不需要的内容)
$ b $ pre $ document.addEventListener(DOMContentLoaded,function(){

var elements = document.getElementsByClassName(header-nav-item);
while(elements.length> 0){
elements [0] .parentNode.removeChild(elements [0]);
}

var element = document.getElementById(topchapter);
element.parentNode.removeChild(element);
element = document.getElementById(wrapper_header);
element.parentNode.removeChild(element);

});

这是我的扩展使用的内容脚本,它在页面加载后删除。在用户看到页面之前,我需要使用什么来修改DOM?

解决方案

使用 MutationObserver document-start注入的内容脚本中 code>实际上在页面加载期间从DOM中删除HTML元素,然后它们被呈现,以便没有闪烁。


  • manifest.json:

      {
    name:删除元素,
    version :1.0,
    content_scripts:[
    {
    matches:[http://somesite.com/*],
    run_at: document_start,
    all_frames:true,
    js:[content.js]
    }
    ],
    manifest_version:2


  • content.js:

      deleteElements('。header-nav-item,#topchapter,#wrapper_header'); 

    function deleteElements(selector){
    //在内容脚本在页面被部分加载后注入的情况下
    doDelete(document.querySelectorAll(selector));

    var mo = new MutationObserver(process);
    mo.observe(document,{subtree:true,childList:true});
    document.addEventListener('DOMContentLoaded',function(){mo.disconnect()});

    函数process(mutation){
    for(var i = 0; i var nodes = mutations [i] .addedNodes; (var j = 0; j< nodes.length; j ++){
    var n = nodes [j];
    if(n.nodeType!= 1)//只处理Node.ELEMENT_NODE
    continue;
    doDelete(n.matches(selector)?[n]:n.querySelectorAll(selector));


    $ b函数doDelete(节点){
    [] .forEach.call(nodes,function(node){node.remove()}) ;
    }
    }

    // Chrome前-34
    if(!Element.prototype.matches)
    Element.prototype.matches = Element.prototype .webkitMatchesSelector;




注意:


  • 观察者回调必须简单而快速,以便在页面加载时不引入滞后,因此循环的普通循环优于 forEach 回调。

  • 作业完成后,最好立即断开观察者,以免不必要地观察页面的其他部分。 添加多个观察者,将所有检查合并为一个

  • 突变数组还包含文本子节点以及添加的元素本身。这就是为什么我们检查 nodeType 是否是 Node.ELEMENT_NODE ,它等于 1
  • 每个变异的 addedNodes 数组通常具有像 DIV ,例如,它可能有一个我们想要删除的元素。因此,我们必须用 querySelector querySelectorAll 来检查它。
  • childNode.remove()自Chrome 23以来运作


I am trying to create an extension that will get rid of certain Page elements (by id or class) before the page is displayed to the screen. I've tried using an event listener on the document with "DOMContentLoaded" as the event but the javascript seems to execute after the page is displayed to the user and then deletes it so it's not as smooth as I want (not showing the unwanted content at all)

document.addEventListener("DOMContentLoaded", function() {

var elements = document.getElementsByClassName("header-nav-item");
while(elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
}

var element = document.getElementById("topchapter");
element.parentNode.removeChild(element);
element = document.getElementById("wrapper_header");
    element.parentNode.removeChild(element);

});

This is the content script that my extension uses which deletes after the page is loaded. What do I need to use to modify the DOM before the pages is seen by the user?

解决方案

Use MutationObserver in the content script injected at document-start to actually delete the HTML elements from DOM during page load before they are rendered so that there's no flickering.

  • manifest.json:

    {
        "name": "Delete elements",
        "version": "1.0",
        "content_scripts": [
            {
                "matches": ["http://somesite.com/*"],
                "run_at": "document_start",
                "all_frames": true,
                "js": ["content.js"]
            }
        ],
        "manifest_version": 2
    }
    

  • content.js:

    deleteElements('.header-nav-item, #topchapter, #wrapper_header');
    
    function deleteElements(selector) {
        // in case the content script was injected after the page is partially loaded
        doDelete(document.querySelectorAll(selector));
    
        var mo = new MutationObserver(process);
        mo.observe(document, {subtree:true, childList:true});
        document.addEventListener('DOMContentLoaded', function() { mo.disconnect() });
    
        function process(mutations) {
            for (var i = 0; i < mutations.length; i++) {
                var nodes = mutations[i].addedNodes;
                for (var j = 0; j < nodes.length; j++) {
                    var n = nodes[j];
                    if (n.nodeType != 1) // only process Node.ELEMENT_NODE
                        continue;
                    doDelete(n.matches(selector) ? [n] : n.querySelectorAll(selector));
                }
            }
        }
        function doDelete(nodes) {
            [].forEach.call(nodes, function(node) { node.remove() });
        }
    }
    
    // Chrome pre-34
    if (!Element.prototype.matches)
        Element.prototype.matches = Element.prototype.webkitMatchesSelector;
    

Notes:

  • The observer callback must be simple and fast in order not to introduce lags during page loading so a plain for loop is better than forEach callbacks.
  • When the job is done it's best to disconnect the observer immediately so that the rest of the page isn't needlessly observed.
  • Don't add multiple observers, incorporate all checks in just one
  • mutations array also contains text subnodes along with the added elements themselves. That's why we check if nodeType is Node.ELEMENT_NODE which equals 1.
  • Each mutation's addedNodes array usually has container elements like DIV, for example, which in turn may have an element we want to delete inside. So we have to examine it with querySelector or querySelectorAll.
  • childNode.remove() works since Chrome 23

这篇关于在页面显示到屏幕之前删除DOM元素(在Chrome扩展中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆