每日 30 秒 ⏱ 巧用可視區域

簡介

可視區域、頁面優化、DOM節點多、圖片懶加載、性能javascript

可視區域是一個前端優化常常出現的名詞,無論是顯示器、手機、平板它們的可視區域範圍都是有限。在這個 有限可視區域 區域裏作到完美顯示和響應,而在這個區域外少作一些操做來減小渲染的壓力、網絡請求壓力。在 每日 30 秒之 對海量數據進行切割 中的使用場景,咱們就是利用了 有限可視區域 只渲染一部分 DOM 節點來減小頁面卡頓。css

既然 可視區域 這麼重要是否有什麼速成祕籍來幫咱們?html

生活終於對我這隻小貓咪動手了

控制住每個元素在可視區域的出現,就能夠扼住命運的後頸隨心所欲:前端

// 該源碼來自於 https://30secondsofcode.org
const inViewport = (el, partiallyVisible = false) => {
    const { top, left, bottom, right } = el.getBoundingClientRect();
    const { innerHeight, innerWidth } = window;
    return partiallyVisible
        ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
        ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
        : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
複製代碼

代碼分析

使用 Element.getBoundingClientRect 方法返回元素的大小及其相對於視口的位置,能夠獲得當前元素相對 可視區域 的座標:java

const { top, left, bottom, right } = el.getBoundingClientRect();
複製代碼

獲得元素的座標信息後,就須要得到 可視區域 的寬高來幫助咱們肯定是否在範圍內:git

const { innerHeight, innerWidth } = window;
複製代碼

先判斷是否須要整個元素都出如今 可視區域github

if (partiallyVisible) {
    // 只須要出如今可視區域 
} else {
    // 須要整個元素都在可視區域內
}
複製代碼

判斷元素頭部或者底部是否在 可視區域 出現:segmentfault

(top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)
複製代碼

判斷元素左部或者右部是否在 可視區域 出現:服務器

(left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)
複製代碼

當須要整個元素都出如今屏幕的時候,須要同時判斷四個相對座標:微信

top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth
複製代碼

使用場景

如今網頁中常常會出現大量的圖片,然而加載大量圖片會影響網頁加載速度,咱們能夠利用 可視區域 來實現圖片的懶加載。爲何要懶加載圖片:

大量的圖片請求會增長服務器的壓力。
  • 使用 CDN 加速來緩解服務器壓力例如 七牛雲
加速用戶的網頁加載速度,當圖片數量巨大須要佔用請求資源和顯示速度。
  • HTTP1 文件限制會對同一個域名限制文件請求數 能夠經過 影子域名 來繞過這個限制。
  • 利用 可視區域 當移動到某個 標誌元素 時再進行更多數據和圖片的加載。
  • 利用佔位圖片來防止頁面塌陷。
用戶訪問頁面有時候只是粗略的一撇。
  • 利用 可視區域 加載部分數據圖片節省網絡流量。
結構
<div class="container">
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
    <div class="img-box img-placeholder" data-src="http://suo.im/5p9IOS"></div>
</div>
複製代碼
樣式
.img-box {
    width: 200px;
    height: 200px;
    margin: 10px 0 10px 10px;
    background: #eee;
    display: inline-block;
}

.img-box > img {
    width: 100%;
    height: 100%;
}
複製代碼
腳本
document.addEventListener('scroll', lazyLoading)
window.onload = () => lazyLoading()

function lazyLoading() {
    const boxs = document.querySelectorAll('.img-placeholder')

    Array.from(boxs).map(box => {
        if (!inViewport(box, true)) return;

        // 獲取圖片地址並清除數據記錄 
        const src = box.getAttribute('data-src');
        box.removeAttribute('data-src');

        // 插入圖片 DOM
        box.innerHTML = `<img src='${src}'>`;

        // 去除佔位 class
        box.className = box.className.replace('img-placeholder', '')
    })
}
複製代碼

一塊兒成長

在困惑的城市裏總少不了並肩同行的 夥伴 讓咱們一塊兒成長。

  • 若是您想讓更多人看到文章能夠點個 點贊
  • 若是您想激勵小二能夠到 Github 給個 小星星
  • 若是您想與小二更多交流添加微信 m353839115

微信公衆號

本文原稿來自 PushMeTop

相關文章
相關標籤/搜索