MutationObserver

MutationObserver

MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。

简单来讲就是使用Mutationboserver可以监听dom节点的属性变化,节点的删除增加等一系列变化

那MutationObserver有啥用呐?

  1. 页面水印的制作

    防止水印被用户删除或者改变水印的dom属性

  2. 页面弹窗广告无法被删除

    对,一些万恶广告就是这么做的

具体用法

以下MDN摘录,详细请自行查看MDN

  1. disconnect()

    阻止 MutationObserver 实例继续接收的通知,直到再次调用其observe()方法,该观察者对象包含的回调函数都不会再被调用。

  2. observe()

    配置MutationObserver在DOM更改匹配给定选项时,通过其回调函数开始接收通知。

  3. takeRecords()

    从MutationObserver的通知队列中删除所有待处理的通知,并将它们返回到MutationRecord对象的新Array中。

阮一峰大佬已经整理一份关于MutationObserver的详细用法,详情请点击下面链接

阮一峰 MutationObserver详解

阮一峰 MutationObserver详解 新版博客

配合canvas实现无法隐藏和删除的水印

var WaterMark = function() {
    this.container = null
    this.defaultOption = {
        id: 'watermark-global',
        width: 300,
        preventTamper: true,
        height: 115,
        text: 'icc-watermark',
        font: '20px Times New Roman',
        rotateDegree: (30 * Math.PI) / 180,
        style: {
            'pointer-events': 'none',
            width: '100%',
            height: '100%',
            top: 0,
            left: 0,
            position: 'fixed',
            'z-index': 5000
        }
    }
    this.canAdd = true
}

//create image base64 url via canvas
WaterMark.prototype.createImageUrl = function(options) {
    var canvas = document.createElement('canvas')
    var text = options.text
    canvas.width = 300
    canvas.height = 150
    var ctx = canvas.getContext('2d')
    ctx.rotate((19 * Math.PI) / 180)
    ctx.font = '15px Microsoft JhengHei'
    ctx.fillStyle = 'rgba(17, 17, 17, 0.10)'
    ctx.textAlign = 'left'
    ctx.textBaseline = 'Middle'
    ctx.fillText(text, canvas.width / 3, canvas.height / 2)
    ctx.rotate(options.rotateDegree)
    return canvas.toDataURL('image/png')
}

WaterMark.prototype.createContainer = function(options, forceCreate) {
    var oldDiv = document.getElementById(options.id)
    var existsOldDiv = typeof oldDiv != 'undefined' && oldDiv != null
    if (!forceCreate && existsOldDiv) {
        return existsOldDiv
    }
    var url = this.createImageUrl(options)
    var div = existsOldDiv ? oldDiv : document.createElement('div')
    div.id = options.id

    var parentEl = options.preventTamper
        ? document.body
        : options.parentEl || document.body

    if (typeof parentEl === 'string') {
        if (parentEl.startsWith('#')) {
            parentEl = parentEl.substring(1)
        }
        parentEl = document.getElementById(parentEl)
    }
    var rect = parentEl.getBoundingClientRect()
    options.style.left = (options.left || rect.left) + 'px'
    options.style.top = (options.top || rect.top) + 'px'
    div.style.cssText = this.getStyleText(options)
    div.setAttribute('class', '')
    div.style.background = 'url(' + url + ') repeat top left'
    !oldDiv && parentEl.appendChild(div)
    return div
}

WaterMark.prototype.getStyleText = function(options) {
    var ret = '',
        style = options.style
    Object.keys(style).forEach(function(k) {
        ret += k + ': ' + style[k] + ';'
    })
    return ret
}

WaterMark.prototype.observe = function(options) {
    var self = this
    self.container = self.createContainer(options, true)
    var target = self.container
    var observer = new MutationObserver(function() {
        observer.disconnect()
        if (self.canAdd) {
            self.container = self.createContainer(options, true)
        }
        var config = {
            attributes: true,
            childList: true,
            characterData: true,
            subtree: true
        }
        observer.observe(target, config)
    })
    var config = {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true
    }
    observer.observe(target, config)
}

WaterMark.prototype.observeBody = function(options) {
    //observe body element, recreate if the element is deleted
    var self = this
    var pObserver = new MutationObserver(function(mutations) {
        mutations.forEach(function(m) {
            var length = m.removedNodes.length
            if (m.type === 'childList' && length > 0) {
                var watermarkNodeRemoved = false
                for (var n = 0; n < length; n++) {
                    if (m.removedNodes[n].id === options.id) {
                        watermarkNodeRemoved = true
                        break
                    }
                }
                if (watermarkNodeRemoved) {
                    self.observe(options, true)
                }
            }
        })
    })
    pObserver.observe(document.body, { childList: true, subtree: true })
}

//初始化水印
WaterMark.prototype.init = function(options) {
    options = !options
        ? this.defaultOption
        : Object.assign({}, this.defaultOption, options)
    this.observe(options)
    this.observeBody(options)
}

//暂时隐藏水印
WaterMark.prototype.destory = function(options) {
    options = !options
        ? this.defaultOption
        : Object.assign({}, this.defaultOption, options)
    var target = document.getElementById(options.id)
    if (target) {
        this.canAdd = false
        target.style.display = 'none'
    }
}

export default WaterMark

chrome插件配合MutationObserver实现广告去除

window.addEventListener("DOMContentLoaded", () => {
  try {
    console.log("插件start");
    var Observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(m) {
        var length = m.addedNodes.length;
        if (m.type === "childList" && length > 0) {
          for (var n = 0; n < length; n++) {
            if (m.addedNodes[n].className === 'advertModal') {
                    let modal = document.querySelectorAll(".advertModal")[0];
                    let dom = document.querySelectorAll(".advertModal-content")[0];
                    if(modal&&dom){
                        dom.remove();
                        modal.style.position = "unset";
                        console.log("插件success");
                    }
              break;
            }
          }
        }
      });
    });
    Observer.observe(document.body, { childList: true, subtree: true });
  } catch (err) {
    console.log("运行错误");
  }
});

chrome插件攻略

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值