你不知道的 JS 高級方法

前言

Js中有一些比較冷門但是非常好用的方法,我在這裏稱之爲高級方法,這些方法沒有被廣泛使用或多或少是因爲存在一些兼容性的問題,不是所有的瀏覽器都讀得懂的。這篇文章主要就是對這些方法做一個總結,有些方法在我們開發過程中有着重要的作用,我們一起來看一下吧。

getBoundingClientRect()

getBoundingClientRect() 是一個用於獲取元素位置和尺寸信息的方法。它返回一個 DOMRect 對象,其提供了元素的大小及其相對於視口的位置,其中包含了以下屬性:

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 需要以下步驟:

  1. 創建一個 IntersectionObserver 實例,傳入一個回調函數和可選的配置對象。
const observer = new IntersectionObserver(callback, options);
const callback = (entries, observer) ={
  // 處理交叉狀態變化的回調函數
};

const options = {
  // 可選配置
};
  1. 將要觀察的目標元素添加到觀察者中。
const target = document.querySelector('#targetElement');
observer.observe(target);
  1. 在回調函數中處理交叉狀態的變化。
const observer = new IntersectionObserver(callback, options);
const callback = (entries, observer) ={
  // 處理交叉狀態變化的回調函數
};

const options = {
  // 可選配置
};

entries 參數是一個包含每個目標元素交叉狀態信息的數組。每個 entry 對象都有以下屬性:

options 對象是可選的配置,其中常用的配置選項包括:

應用場景

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 次。這意味着我們可以在每次重繪之前更新動畫的狀態,並確保動畫流暢運行,而不會對瀏覽器的性能造成影響。

setIntervalsetTimeout它可以讓我們在指定的時間間隔內重複執行一個操作,不會考慮瀏覽器的重繪,而是按照指定的時間間隔執行回調函數,可能會被延遲執行,從而影響動畫的流暢度。

效果對比

我們設置了兩個容器,分別用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會有卡頓現象。

小結

本文主要介紹了在 Js 中五個不常用但很高級的方法,看完這篇文章希望對你學習有所幫助。最後祝大家週末愉快,我們下篇文章見。

關於本文

作者:一拾九

https://juejin.cn/post/7242983917603405883

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/iotxCErmALvbFaOcuj5p_w