MutationObserver 監(jiān)聽DOM

介紹

MutationObserver接口提供了監(jiān)視對DOM樹所做更改的能力凸主。

構(gòu)造函數(shù)

MutationObserver()創(chuàng)建并返回一個新的MutationObserver它會在指定的DOM發(fā)生變化時被調(diào)用既绕。

new MutationObserver(callback):當(dāng)每次DOM發(fā)生變化的時候都會觸發(fā)callback。

等所有的DOM操作完成之后一次執(zhí)行(異步)

方法
  • disconnect()

    阻止 MutationObserver 實(shí)例繼續(xù)接收的通知芥被,直到再次調(diào)用其observe()方法,該觀察者對象包含的回調(diào)函數(shù)都不會再被調(diào)用籽腕。

  • observe()

    配置MutationObserver在DOM更改匹配給定選項(xiàng)時乾蓬,通過其回調(diào)函數(shù)開始接收通知。

  • takeRecords()

    從MutationObserver的通知隊(duì)列中刪除所有待處理的通知壁榕,并將它們返回到MutationRecord對象的新Array中矛紫。

使用
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>MutationObserver</title>
</head>
<body>
  <div id="simple" class="test"> simple </div>
</body>
<script>
  // mutations 變動數(shù)組 observer 觀察器實(shí)例
  var observer = new MutationObserver(function (mutations, observer) {
    mutations.forEach(function(mutation) {
      // 執(zhí)行具體的操作
      // 例如:頁面劫持
      console.log(mutation)
    })
  })
  // 開始監(jiān)聽頁面根元素 html 變化
  observer.observe(document.getElementById("simple"), {
    attributes: true, // 屬性變動
    characterData: true, // 節(jié)點(diǎn)內(nèi)容或節(jié)點(diǎn)文本的變動
    childList: true, // 子節(jié)點(diǎn)的變動
    subtree: true, // 表示是否將觀察器應(yīng)用于該節(jié)點(diǎn)的所有后代節(jié)點(diǎn)
    attributeOldValue: true, // 表示觀察 attributes 變動時,是否需要記錄變動前的屬性值
    characterDataOldValue: true, // 表示觀察 characterData 變動時牌里,是否需要記錄變動前的值
    attributeFilter: ["style"] // 數(shù)組颊咬,表示需要觀察的特定屬性 (比如: ["class", "src"])
  });

  // document.getElementById("simple").innerText = 123;
  document.getElementById("simple").firstChild.nodeValue="test";
  // document.getElementById("simple").setAttribute("style", "background-color:blue; color:red; border:1px solid black");
  // document.getElementById("simple").style.height = "123px";
  // document.getElementById("simple").innerHTML = "<p>rrr</p>";
  

  // // 停止觀察, 調(diào)用該方法后牡辽,DOM 再發(fā)生變動喳篇,也不會觸發(fā)觀察器
  // observer.disconnect();
  // // 清除變動記錄,即不再處理未處理的變動态辛,改方法返回變動記錄的數(shù)組麸澜。
  // observer.takeRecords();

  // // 保存所有沒有被觀察器處理的變動
  // var changes = observer.takeRecords();
  // console.log(changes, "changes");
  // // 停止觀察
  // observer.disconnect();

  // MutationRecord 對象
  // type: 觀察的變動類型
  // target:發(fā)生變動的DOM節(jié)點(diǎn)
  // addedNodes:新增的DOM節(jié)點(diǎn)
  // removeNodes:刪除的DOM節(jié)點(diǎn)
  // previousSibling:前一個同級節(jié)點(diǎn),如果沒有則返回null
  // nextSibling:下一個同級節(jié)點(diǎn)奏黑,如果沒有則返回null
  // attributeName:發(fā)生變動的屬性炊邦。如果這只了 attributeFilter,則只返回預(yù)先指定的屬性
  // oldValue:變動前的值熟史。這個屬性只對 attribute和characterData變動有效馁害,如果發(fā)生childList變動,則返回null
</script>
</html>
示例
  • 水印不可刪

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div id="content"></div>
    </body>
    <script>
      function drawCanvas() {
        let content = document.getElementById("content");
        let divContainer = document.body.appendChild(document.createElement('div'));
        content.appendChild(divContainer);
        let waterMarkercanvas = document.createElement('canvas');
        let context = waterMarkercanvas.getContext('2d');
    
        divContainer.appendChild(waterMarkercanvas);
        divContainer.id = 'divContainer'
        let backgroundUrl = null;
    
        divContainer.style.height = window.innerHeight + 'px';
        divContainer.style.width = window.innerWidth + 'px';
    
    
        waterMarkercanvas.width = "400";
        waterMarkercanvas.height = "400";
    
        context.font = "20px";
        context.textAlign = "center";
        context.fillStyle = "#0000ff";
    
        context.fillText("我是水印", 100, 100);
    
        backgroundUrl = waterMarkercanvas.toDataURL('image/png');
        divContainer.style.backgroundImage = `url(${backgroundUrl})`;
      }
      drawCanvas();
      let callback = (mutations) => {
        mutations.forEach(mutation => {
            console.log(mutation,"mutation");
            if(mutation.removedNodes.length > 0 && mutation.removedNodes[0].id == "divContainer" && mutation.addedNodes.length <= 0) {
              setTimeout(function() {
                console.log("新增")
                drawCanvas();
              }, 3000)
            }
        });
      };
      let observer = new MutationObserver(callback);
      observer.observe(document.getElementById("content"), {
        childList: true,
        // subtree: true
      });
      console.log(document.getElementsByTagName("div"))
      setTimeout(function() {
        console.log("刪除")
        document.getElementById("content").removeChild(document.getElementById("divContainer"));
      }, 3000)
    </script>
    </html>
    
  • 防止運(yùn)營劫持:監(jiān)控dom蹂匹,不在白名單內(nèi)和安全標(biāo)簽內(nèi)的script或者iframe碘菜,都給予remove刪除處理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市炉媒,隨后出現(xiàn)的幾起案子踪区,更是在濱河造成了極大的恐慌,老刑警劉巖吊骤,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缎岗,死亡現(xiàn)場離奇詭異,居然都是意外死亡白粉,警方通過查閱死者的電腦和手機(jī)传泊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸭巴,“玉大人眷细,你說我怎么就攤上這事【樽妫” “怎么了溪椎?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長恬口。 經(jīng)常有香客問我校读,道長,這世上最難降的妖魔是什么祖能? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任歉秫,我火速辦了婚禮,結(jié)果婚禮上养铸,老公的妹妹穿的比我還像新娘雁芙。我一直安慰自己,他們只是感情好钞螟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布兔甘。 她就那樣靜靜地躺著,像睡著了一般筛圆。 火紅的嫁衣襯著肌膚如雪裂明。 梳的紋絲不亂的頭發(fā)上椿浓,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天太援,我揣著相機(jī)與錄音,去河邊找鬼扳碍。 笑死提岔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笋敞。 我是一名探鬼主播碱蒙,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赛惩?” 一聲冷哼從身側(cè)響起哀墓,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喷兼,沒想到半個月后篮绰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡季惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年吠各,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勉抓。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡贾漏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出藕筋,到底是詐尸還是另有隱情纵散,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布隐圾,位于F島的核電站困食,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏翎承。R本人自食惡果不足惜硕盹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叨咖。 院中可真熱鬧瘩例,春花似錦、人聲如沸甸各。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趣倾。三九已至聘惦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間儒恋,已是汗流浹背善绎。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诫尽,地道東北人禀酱。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像牧嫉,于是被迫代替她去往敵國和親剂跟。 傳聞我的和親對象是個殘疾皇子减途,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 導(dǎo)語:前段時間做某系統(tǒng)審核后臺,出現(xiàn)了審核人員截圖把內(nèi)容外泄露的情況曹洽,雖然截圖內(nèi)容不是特別敏感鳍置,但是安全問題還是不...
    李亞_45be閱讀 1,180評論 0 0
  • #JavaScript best practices JS最佳實(shí)踐## 0 簡介> 最佳實(shí)踐起初比較棘手,但最終會...
    yanlee26閱讀 659評論 0 1
  • MutationObserver接口提供了監(jiān)視對DOM樹所做更改的能力送淆。它被設(shè)計(jì)為舊的Mutation Event...
    wwmin_閱讀 2,893評論 0 52
  • 一墓捻、概念介紹 Vue.js和React.js分別是目前國內(nèi)和國外最火的前端框架,框架跟類庫/插件不同坊夫,框架是一套完...
    劉遠(yuǎn)舟閱讀 1,036評論 0 0
  • 前言開門見山砖第,這篇文章,適合 「 初級前端 」 环凿,如果你還在校招的話梧兼,或者還在求職的話,可以看看本文智听,找一找靈感羽杰,...
    WEB前端含光閱讀 1,339評論 1 2