您好,登錄后才能下訂單哦!
這篇文章主要介紹“DataV全屏容器組件源碼分析”,在日常操作中,相信很多人在DataV全屏容器組件源碼分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”DataV全屏容器組件源碼分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
數據可視化頁面一般在瀏覽器中進行全屏展示,全屏容器將根據屏幕比例及當前瀏覽器窗口大小,自動進行縮放處理。瀏覽器全屏后,全屏容器將充滿屏幕。
它的源碼位置
看下它的DOM結構,很簡單
<div id="dv-full-screen-container" :ref="ref"> <template v-if="ready"> <slot></slot> </template> </div>
接下來重點看下它的JS實現,它的代碼中混入了autoResize.js,所以我們需要兩個文件一起看,不然會對突然出現的變量很奇怪。(如果覺得分開不便于閱讀,其實我們可以把它合在一起來閱讀,是一樣的)
第1步、mounted(組件掛載時,這一時期可對dom進行操作)
mounted () { const { autoResizeMixinInit } = this autoResizeMixinInit() },
第2步、autoResizeMixinInit函數
methods: { async autoResizeMixinInit () { const { initWH, getDebounceInitWHFun, bindDomResizeCallback, afterAutoResizeMixinInit } = this await initWH(false) getDebounceInitWHFun() bindDomResizeCallback() if (typeof afterAutoResizeMixinInit === 'function') afterAutoResizeMixinInit() }, }
這其中調用了幾個函數,我們來看看這些函數的作用。
2.1、initWH函數
// 初始化寬高 initWH (resize = true) { const { $nextTick, $refs, ref, onResize } = this return new Promise(resolve => { $nextTick(_ => { const dom = this.dom = $refs[ref] this.width = dom ? dom.clientWidth : 0 this.height = dom ? dom.clientHeight : 0 if (!dom) { console.warn('DataV: Failed to get dom node, component rendering may be abnormal!') } else if (!this.width || !this.height) { console.warn('DataV: Component width or height is 0px, rendering abnormality may occur!') } if (typeof onResize === 'function' && resize) onResize() resolve() }) }) },
這個函數的作用很簡單,就是在DOM渲染成功后,獲取這個組件dom的寬高,返回一個Promise異步函數,作用就是:保證這個dom已經渲染好了,再去執行其他函數。
2.1.1、onResize
onResize () { const { setAppScale } = this setAppScale() }
resize為true,即窗口大小變化、dom的style改變時要重新設置dom的縮放比例。
2.2、getDebounceInitWHFun
getDebounceInitWHFun () { const { initWH } = this this.debounceInitWHFun = debounce(100, initWH) },
獲取一個經過防抖的initWH函數。即debounceInitWHFun。
2.3、bindDomResizeCallback
// 監聽dom元素變化 bindDomResizeCallback () { const { dom, debounceInitWHFun } = this this.domObserver = observerDomResize(dom, debounceInitWHFun) window.addEventListener('resize', debounceInitWHFun) },
很重要的一步,其中使用了observerDomResize來對這個組件dom進行監聽。
需要監聽的DOM變化:
窗口大小改變時觸發的事件
dom的樣式改變時觸發
第一個直接使用window監聽resize事件即可。
第二個對dom元素的監聽,我們就需要使用MutationObserver來做了。
MutationObserver用來監視 DOM 變動。DOM 的任何變動,比如節點的增減、屬性的變動、文本內容的變動都會觸發MutationObserver事件。
封裝一個observerDomResize函數來對dom的style屬性變化進行監聽
export function observerDomResize (dom, callback) { const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver const observer = new MutationObserver(callback) observer.observe(dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true }) return observer }
attributes:屬性的變動
attributeFilter:表示需要觀察的特定屬性
attributeOldValue:布爾值,表示觀察attributes變動時,是否需要記錄變動前的屬性值。
2.4、afterAutoResizeMixinInit
afterAutoResizeMixinInit () { const { initConfig, setAppScale } = this initConfig() setAppScale() this.ready = true },
組件dom節點渲染出來后,設置ready為true,再渲染插槽中的DOM元素。
2.4.1、initConfig
initConfig () { const { dom } = this // 當前屏幕分辨率 const { width, height } = screen this.allWidth = width dom.style.width = `${width}px` dom.style.height = `${height}px` },
作用:
獲取當前設備屏幕的分辨率
將這個分辨率寬高設置為組件DOM的寬高
2.4.2、setAppScale
setAppScale () { const { allWidth, dom } = this const currentWidth = document.body.clientWidth dom.style.transform = `scale(${currentWidth / allWidth})` },
它的作用是改變當前DOM的縮放比率。
縮放比率 = 當前窗口的可視寬度 / 當前設備的屏幕分辨率(寬度)
第3步、beforeDestroy(組件卸載時)
beforeDestroy () { const { unbindDomResizeCallback } = this unbindDomResizeCallback() }
我們之前對于dom的style屬性和window的resize都做了監聽,所以當我們組件卸載時這些監聽事件也需要移除,如果不移除,那么到其他頁面,做這些操作,監聽事件仍然存在,但其實我們已經不需要再對他監聽了,反而會造成性能浪費。
3.1、unbindDomResizeCallback
unbindDomResizeCallback () { let { domObserver, debounceInitWHFun } = this if (!domObserver) return domObserver.disconnect() domObserver.takeRecords() domObserver = null window.removeEventListener('resize', debounceInitWHFun) }
disconnect方法用來停止觀察。調用該方法后,DOM 再發生變動,也不會觸發觀察器。
takeRecords用來清除變動記錄,即不再處理未處理的變動。該方法返回變動記錄的數組。
到此,關于“DataV全屏容器組件源碼分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。