這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在Js中有一些比較冷門但是非常好用的方法,我在這裡稱之為高級方法,這些方法沒有被廣泛使用或多或少是因為存在一些相容性的問題,不是所有的瀏覽器都讀得懂的。這篇文章主要就是對這些方法做一個總結,有些方法在我們開發過程中有著重要的作用,我 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前言
在Js
中有一些比較冷門但是非常好用的方法,我在這裡稱之為高級方法,這些方法沒有被廣泛使用或多或少是因為存在一些相容性的問題,不是所有的瀏覽器都讀得懂的。這篇文章主要就是對這些方法做一個總結,有些方法在我們開發過程中有著重要的作用,我們一起來看一下吧。
getBoundingClientRect()
getBoundingClientRect()
是一個用於獲取元素位置和尺寸信息的方法。它返回一個 DOMRect對象,其提供了元素的大小及其相對於視口的位置,其中包含了以下屬性:
x
:元素左邊界相對於視口的 x 坐標。y
:元素上邊界相對於視口的 y 坐標。width
:元素的寬度。height
:元素的高度。top
:元素上邊界相對於視口頂部的距離。right
:元素右邊界相對於視口左側的距離。bottom
:元素下邊界相對於視口頂部的距離。left
:元素左邊界相對於視口左側的距離。
const box = document.getElementById('box'); const rect = box.getBoundingClientRect(); console.log(rect.x); // 元素左邊界相對於視口的 x 坐標 console.log(rect.y); // 元素上邊界相對於視口的 y 坐標 console.log(rect.width); // 元素的寬度 console.log(rect.height); // 元素的高度 console.log(rect.top); // 元素上邊界相對於視口頂部的距離 console.log(rect.right); // 元素右邊界相對於視口左側的距離 console.log(rect.bottom); // 元素下邊界相對於視口頂部的距離 console.log(rect.left); // 元素左邊界相對於視口左側的距離
為了更好地理解,我在頁面上設置了一個容器,其對應屬性看下圖:
應用場景
這個方法通常用於需要獲取元素在視口中的位置和尺寸信息的場景,比如實現拖拽、定位或響應式佈局等,相容性很好,一般用滾動事件比較多。
特殊場景會用上,比如你登錄了淘寶的網頁,當你下拉滑塊的時候,下麵的圖片不會立即載入出來,有一個懶載入的效果。當上面一張圖片沒在可視區內時,就開始載入下麵的圖片。
下麵代碼就是判斷一個容器是否出現在可視視窗內:
const box = document.getElementById('box') window.onscroll = function () {//window.addEventListener('scroll',()=>{}) console.log(checkInView(box)); } function checkInView(dom) { const { top, left, bottom, right } = dom.getBoundingClientRect(); return top > 0 && left > 0 && bottom <= (window.innerHeight || document.documentElement.clientHeight) && right <= (window.innerWidth || document.documentElement.clientWidth) }
當容器在可視區域內就輸出true
,否則就是false
。
intersectionObserver
IntersectionObserver
是一個構造函數,可以接收兩個參數,第一個參數是一個回調函數,第二個參數是一個對象。這個方法用於觀察元素相交情況,它可以非同步地監聽一個或多個目標元素與其祖先元素或視口之間的交叉狀態。它提供了一種有效的方法來檢測元素是否可見或進入視口。
用法
使用 IntersectionObserver
需要以下步驟:
- 創建一個
IntersectionObserver
實例,傳入一個回調函數和可選的配置對象。
const observer = new IntersectionObserver(callback, options); const callback = (entries, observer) => { // 處理交叉狀態變化的回調函數 }; const options = { // 可選配置 };
- 將要觀察的目標元素添加到觀察者中。
const target = document.querySelector('#targetElement'); observer.observe(target);
- 在回調函數中處理交叉狀態的變化。
const callback = (entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { // 元素進入視口 } else { // 元素離開視口 } }); };
entries
參數是一個包含每個目標元素交叉狀態信息的數組。每個 entry
對象都有以下屬性:
target
:觀察的目標元素。intersectionRatio
:目標元素與視口的交叉比例,值在 0 到 1 之間。isIntersecting
:目標元素是否與視口相交。intersectionRect
:目標元素與視口的交叉區域的位置和尺寸信息。
options
對象是可選的配置,其中常用的配置選項包括:
root
:指定觀察器的根元素,預設為視口。rootMargin
:設置根元素的外邊距,用於擴大或縮小交叉區域。threshold
:指定交叉比例的閾值,可以是單個數值或由多個數值組成的數組。
應用場景
IntersectionObserver
適用於實現懶載入、無限滾動、廣告展示和可視化統計等場景,同樣可以判斷元素是否在某一個容器內,不會引起迴流。
createNodeIterator()
createNodeIterator()
方法是 DOM API 中的一個方法,用於創建一個 NodeIterator 對象,可以用於遍歷文檔樹中的一組 DOM 節點。
通俗一點來講就是它可以遍歷 DOM 結構,把 DOM 變成可遍歷的。
比較偏的面試考點
這種方法算是一個比較偏的面試考點,面試官問你怎樣實現遍歷 DOM 結構?其實就可以用到這個方法。但是大多數程式員答不上來這個問題,因為我們在日常開發中這個方法用得極少。這個方法常在框架源碼中體現。
應用
<body> <div id="app"> <p>hello</p> <div class="title">標題</div> <div> <div class="content">內容</div> </div> </div> <script> const body = document.getElementsByTagName('body')[0] const item = document.createNodeIterator(body)//讓body變成可遍歷的 let root = item.nextNode() // 下一層 while (root) { console.log(root); if (root.nodeType !== 3) { root.setAttribute('data-index', 123)//給每個節點添加一個屬性 } root = item.nextNode() } </script> </body>上面代碼成功遍歷到了各個 DOM 結構:
並且在每個 DOM 節點上都添加了data-index = "123"
。
getComputedStyle()
getComputedStyle()
是一個可以獲取當前元素所有最終使用的CSS屬性值的方法。返回的是一個CSS樣式聲明對象。
這個方法有兩個參數,第一個參數是你想要獲取哪個元素的 CSS ,第二個參數是一個偽元素。
用法
<style> #box { width: 200px; height: 200px; background-color: cornflowerblue; position: relative; } #box::after { content: ""; width: 50px; height: 50px; background: #000; position: absolute; top: 0; left: 0; } </style> const box = document.getElementById('box') const style = window.getComputedStyle(box, 'after') const height = style.getPropertyValue('height') const width = style.getPropertyValue('width') console.log(style); console.log(width, height);
上述代碼輸出結果為:
有一個 id 為 box 容器的 CSS 樣式聲明對象,以及偽元素的寬高。
requestAnimationFrame()
上面4種方法我們可能用得不是很多,但是requestAnimationFrame
方法相對使用較多。requestAnimationFrame()
是一個用於在下一次瀏覽器重繪之前調用指定函數的方法,它是 HTML5 提供的 API。
與setInterval和setTimeout
requestAnimationFrame
的調用頻率通常為每秒60次。這意味著我們可以在每次重繪之前更新動畫的狀態,並確保動畫流暢運行,而不會對瀏覽器的性能造成影響。
setInterval
與setTimeout
它可以讓我們在指定的時間間隔內重覆執行一個操作,不會考慮瀏覽器的重繪,而是按照指定的時間間隔執行回調函數,可能會被延遲執行,從而影響動畫的流暢度。
效果對比
我們設置了兩個容器,分別用requestAnimationFrame()
方法和setTimeout
方法進行平移效果,Js 代碼如下所示:
let distance = 0 let box = document.getElementById('box') let box2 = document.getElementById('box2') window.addEventListener('click', function () { requestAnimationFrame(function move() { box.style.transform = `translateX(${distance++}px)` requestAnimationFrame(move)//遞歸 }) setTimeout(function change() { box2.style.transform = `translateX(${distance++}px)` setTimeout(change, 17) }, 17) })
效果圖如下:
可能我們肉眼看得不是很清楚,但是確實下麵的圖形平移沒有上面圖形流暢,用setTimeout
會有卡頓現象。