MutationObserver 是一個觀察對象,提供用來當DOM樹發生變化時開發者能夠根據發生的變化,進行邏輯的變化。
就像三體中的水滴同樣,當地球上出現大型強子對撞研究時,會觸發必定的邏輯來鎖死地球的科學研究。git
主要說observe()方法,在實現水印不可刪除的過程當中,主要須要應對的邏輯有兩個,第一種是對水印節點的修改,第二種是對水印節點的刪除。
先說第一種,observe( Node target, optional MutationObserverInit options ),接受兩個參數,第一個是目標節點,第二個是目標節點須要被監控的屬性,包括屬性,子節點,甚至全部後代節點均可以監控。github
drawCanvas() { let divContainer = document.body.appendChild(document.createElement('div')); 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 = this.option.canvasWidth; waterMarkercanvas.height = this.option.canvasHeight; context.font =this.option.font; context.textAlign = this.option.textAlign; context.fillStyle = this.option.textStyle; context.translate(waterMarkercanvas.width / 2,waterMarkercanvas.height / 2); context.rotate(this.option.degree * Math.PI / 180); context.fillText(this.option.text, 0, 0); backgroundUrl = waterMarkercanvas.toDataURL('image/png'); divContainer.style.backgroundImage = `url(${backgroundUrl})`; }
在上面的代碼裏,我首先canvas畫出來以後,轉爲png格式的圖片,最後設置成了div的背景圖片。canvas
也就是說id爲divContainer的div就是我須要監控的dom節點。這時我只須要app
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { this.drawCnvas(); }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer'), config); }
就能夠實如今用戶修改divContainer這個節點是實現canvas的重繪。dom
第二種,由於MutationObserver本山來說,是不支持監控本自己節點的刪除操做的,也就是說,我若是刪除了divContainer這個節點,是沒法實現canvas的重繪的。
那麼,這時就須要到一個新的辦法了,那就是監控body節點函數
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { console.log(mo.removeNodes) // this.drawCanvas(); // console.log('detect canvas change and redraw') }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer').parentNode, config); }
由於在第一段代碼中,咱們把該節點做爲了body節點的子節點,若是該節點變化,body節點的水滴確定能夠檢測到,而且完成重繪。由於在咱們的開發中,body節點承載着全部的頁面內容,若刪除body節點那麼也就沒有水印的意義了。
這時須要一個就須要一個MutationObserver()中的一個MutationRecord對象。
this
能夠看到MutationObserver()有一個takeRecords函數來紀錄監控中全部節點增查刪改的操做,而且返回到MutationRecord對象中。
url
能夠看到我執行了removeNode的操做而且被記錄在了MutationRecord這個對象中。spa
canvasObserver() { this.drawCanvas(); let canvasObserver = new MutationObserver((mo) => { console.log(mo[0].removedNodes) // this.drawCanvas(); // console.log('detect canvas change and redraw') }); let config = { attributes: true, childList: true, characterData: true }; console.log canvasObserver.observe(document.querySelector('#divContainer').parentNode, config); }
這是修改後的代碼,咱們只要匹配一個被刪除的div和canvas的div是一致的就能夠進行下一步的重繪操做了。code
https://github.com/AplloBattl...
這是github地址。