成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一次DOM曝光封裝歷程

開發 前端
當我以為已經夠用時,某次需求需要監聽 DOM 在某個 div 內橫向滑動的曝光,發現它并不支持!而后面一些曝光策略對比的文章說到這個 getBoundingClientRect API 會引起性能問題。

隨著最近曝光埋點的需求越來越頻繁,就想把之前寫好的曝光邏輯抽出來封裝了一下作為公用。

初版

邏輯:window.scroll 監聽滾動 + 使用 getBoundingClientRect() 相對于視口位置實現

具體代碼如下:

function buryExposure (el, fn) {
    /*
    * 省略一些邊界判斷
    * ......
    **/
    let elEnter = false; // dom是否進入可視區域
    el.exposure = () => {
        const { top } = el.getBoundingClientRect();
        if (top > 0 && top < window.screen.availHeight) {
            if (!elEnter) {
                elEnter = true;
                fn(el)
            }
        } else {
            elEnter = false;
        };
    }
    document.addEventListener('scroll', el.exposure);
}

回調傳出 el ,一般為頁面注銷時注銷對應滾動事件: el.exposure

其中兩個點

第一個:

// 判斷上邊距出現在視口內,則判定為曝光
const { top } = el.getBoundingClientRect();
if (top > 0 && top < window.screen.availHeight)

其中這里的 top 以及其他邊距對應視口計算方式可能和你想象的不一樣,上圖摘自 你真的會用getBoundingClientRect 嗎 (https://juejin.im/entry/59c1fd23f265da06594316a9), 它對這個屬性講的比較詳細可以看看

第二個:

let elEnter = false; //

用一個變量來控制當 dom 已經曝光則不再持續,直到 dom 離開視口,重新計算

重寫

當我以為已經夠用時,某次需求需要監聽 DOM 在某個 div 內橫向滑動的曝光,發現它并不支持!而后面一些曝光策略對比的文章說到這個 getBoundingClientRect API 會引起性能問題

不相信的你可以試一下!!!

于是我就開啟 google 大法和在掘金社區內搜一些曝光的文章,然后我就發現了新大陸!

window.IntersectionObserver

這次曝光的主角:優先使用異步觀察目標元素與祖先元素或頂級文檔viewport的交集中的變化的方法

關于他的具體介紹,我這里簡單講一下我用到的屬性,具體可查閱 超好用的 API 之 IntersectionObserver (https://juejin.im/post/5d11ced1f265da1b7004b6f7) 或者 MDN (https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver)

主要使用如下:

const io = new IntersectionObserver(callback, options)
io.observe(DOM)
  • callback 回調函數,options 是配置參數
  • io.observe 觀察函數,DOM 為被觀察對象

主要兩點

1.options 的配置為:

const observerOptions = {
    root: null,  // 默認使用視口作為交集對象
    rootMargin: '0px', // 無樣式
    threshold: [...Array(100).keys()].map(x => x / 100) // 監聽交集時的每0.01變化觸發callback回調
}

2.callback 函數如下:

(entries) => {
    // 過程性監聽
    entries.forEach((item) => {
        if (item.intersectionRatio > 0 && item.intersectionRatio <= 1) { // 部分顯示即為顯示
            // todo....
        } else if (item.intersectionRatio === 0) { // 不可見時恢復
            // todo...
        }
    });
}

曝光的判斷來自以下第二種(部分顯示則曝光):

  • intersectionRatio === 1:則監聽對象完整顯示
  • intersectionRatio > 0 && intersectionRatio < 1 : 則監聽對象部分顯示
  • intersectionRatio === 0:則監聽對象不顯示其實 entries[] 子元素對象還有一個屬性:isIntersecting

返回一個布爾值,下列兩種操作均會觸發 callback:

  1. 如果目標元素出現在 root 可視區,返回 true。
  2. 如果從 root 可視區消失,返回 false

按理說應該是使用它,但是發現不適合現實場景!!!

比如 類 banner 橫向移動 (https://jsbin.com/vuzujiw/6/edit?html,css,js,console,output),我第一調試的時候就碰到了

用戶要看的子元素是被父元素給限制住了,但是對于 isIntersecting 它來講是出現在視口內的。

最終版

考慮兼容性:

// 使用w3c出的polyfill
require('intersection-observer');

主要邏輯如下:

/**
 * DOM曝光
 * @param {object} options 配置參數
 * options @param {Array} DOMs 要被監聽的DOM列表
 * options @param {Function} callback[type, io] 回調,傳入參數
 * options @param {DOM} parentDom 子元素的對應父元素
 */
export default function expose (options = {}) {
    if (!options.DOMs || !options.callback) {
        console.error('Error: 傳入監聽DOM或者回調函數');
        return;
    }
    const observerOptions = {
        root: null,
        rootMargin: '0px',
        threshold: [...Array(100).keys()].map(x => x / 100)
    };
    options.parentDom && (observerOptions.root = options.parentDom);
    // 優先使用異步觀察目標元素與祖先元素或頂級文檔viewport的交集中的變化的方法
    if (window.IntersectionObserver) {
        let elEnter = false; // dom是否進入可視區域
        const io = new IntersectionObserver((entries) => {
            // 回調包裝
            const fn = () => options.callback({ io });
            // 過程性監聽
            entries.forEach((item) => {
                if (!elEnter && item.intersectionRatio > 0 && item.intersectionRatio <= 1) { // 部分顯示即為顯示
                    fn();
                    elEnter = true;
                } else if (item.intersectionRatio === 0) { // 不可見時恢復
                    elEnter = false;
                }
            });
        }, observerOptions);
        // 監聽DOM
        options.DOMs.forEach(DOM => io.observe(DOM));
    }
}

參考文獻

你真的會用 getBoundingClientRect 嗎(https://juejin.im/entry/59c1fd23f265da06594316a9)

責任編輯:武曉燕 來源: 政采云技術
相關推薦

2014-08-11 09:31:52

2022-04-22 10:51:45

TSaxios前端

2011-06-28 10:41:50

DBA

2021-12-27 10:08:16

Python編程語言

2020-10-24 13:50:59

Python編程語言

2023-10-23 18:50:52

webservice

2010-02-26 09:22:06

聯通削減部門

2020-10-18 12:53:29

黑科技網站軟件

2020-03-10 07:51:35

面試諷刺標準

2020-03-18 13:07:16

華為

2017-01-23 12:40:45

設計演講報表數據

2019-10-17 09:07:40

互聯網數據技術

2011-07-21 21:01:37

諾基亞塞班蘋果

2020-12-29 10:25:07

漏洞JSONP注入

2011-04-07 11:20:21

SQLServer

2010-01-25 22:11:13

2012-08-28 09:21:59

Ajax查錯經歷Web

2021-11-01 17:29:02

Windows系統Fork

2021-11-11 16:14:04

Kubernetes

2017-02-28 11:13:36

華為
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 人干人人 | 日韩视频国产 | 精品一区二区三区不卡 | 黄色一级毛片免费看 | 成人免费视频播放 | 中文字幕精品一区二区三区精品 | 欧亚av在线 | 国产精品视屏 | 久久高清国产 | 日韩一| 久久天天躁狠狠躁夜夜躁2014 | 国产美女在线免费观看 | 97视频成人 | 欧美精品一区二区三区在线 | 久久久久久艹 | 欧美日韩国产精品激情在线播放 | 青青草一区 | 欧美日韩在线视频一区 | 亚洲国产成人精品女人久久久 | 超碰在线观看97 | 欧美a级成人淫片免费看 | 中文精品视频 | 无码国模国产在线观看 | 国产精品日韩欧美一区二区三区 | 午夜看片网站 | 久久小视频 | 日韩精品一区二区三区在线播放 | 国产一区影院 | 成人国产在线视频 | 福利片在线观看 | 中文字幕乱码一区二区三区 | 欧美一区二区三区大片 | 日韩一区在线播放 | 毛片一级黄色 | 精品国产乱码久久久久久久久 | 国产一区二区在线免费观看 | 亚洲综合成人网 | 91视频一区二区三区 | 中文字幕一级 | 国产电影一区二区在线观看 | 久久在线视频 |