javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > js监听元素出现可视区域

js监听元素是否出现在可视区域详解(IntersectionObserver)

作者:甩锅工程师

这篇文章主要给大家介绍了关于js监听元素是否出现在可视区域(IntersectionObserver)的相关资料, IntersectionObserver是一个JavaScript API,用于监测一个元素与其父元素或视窗的交叉状态,需要的朋友可以参考下

观察者模式监听判断dom元素是否在可视区域内

本项目是使用vue3的写法。

1.IntersectionObserver

IntersectionObserver可以用来自动监听元素是否进入了设备的可视区域之内,而不需要频繁的计算来做这个判断。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"

const observer = new IntersectionObserver(callback, option);

IntersectionObserver 是浏览器原生提供的构造函数,接受两个参数:

构造函数的返回值是一个观察器实例。实例一共有4个方法:

1.1 observe 方法

该方法需要接收一个target参数,值是Element类型,用来指定被监听的目标元素

// 获取元素
const target = document.getElementById("dom");

// 开始观察
io.observe(target);

1.2 unobserve 方法

该方法需要接收一个target参数,值是Element类型,用来指定停止监听的目标元素

// 获取元素
const target = document.getElementById("dom");

// 停止观察
io.unobserve(target);

1.3 disconnect 方法

该方法不需要接收参数,用来关闭观察器

// 关闭观察器
io.disconnect();
// 页面加载时监听元素
onMounted(() => {
	var demo3 = document.querySelector('document.querySelector(dom))  //  获取元素
	var observer = new IntersectionObserver((mutaions)=>{  // 创建IntersectionObserver对象
	        console.log(mutaions[0].isIntersecting)
	      })
	observer.observe(demo3)       // 需要监听的元素 
}       

1.4 takeRecords 方法

该方法不需要接收参数,返回所有被观察的对象,返回值是一个数组

// 获取被观察元素
const observerList = io.takeRecords();

1.5 callback 参数

目标元素的可见性变化时,就会调用观察器的回调函数callback。

callback一般会触发两次。一次是目标元素刚刚进入视口,另一次是完全离开视口。

const io = new IntersectionObserver((changes, observer) => {
  console.log(changes);
  console.log(observer);
});

1.6 options

2. IntersectionObserverEntry 对象

changes数组中的每一项都是一个IntersectionObserverEntry 对象

3. 是否在可视区域

onMounted(() => {
	var observer = new IntersectionObserver((entries) => {
		  console.log(111111, entries[0].isIntersecting);
		  dataMap.showMyBox = !entries[0].isIntersecting; //返回true代表在页面可视区域,false代表不在页面可视区域。
		});
		 observer.observe(document.querySelector(dom));
}
// 页面卸载时可解绑
onBeforeUnmount(() => {
	  if (observer) {
		    observer.unobserve(document.querySelector(dom)); //解绑元素
		    observer.disconnect(); //停止监听
	  }
});

4. 图片懒加载

使用 IntersectionObserver 非常容易实现图片懒加载,首先需要观察懒加载元素,然后等元素进入可视区域后设置图片 src;同时,还可以结合 IntersectionObserver.rootMargin 实现提前加载图片,一般可以设置为 1~2 倍浏览器窗口的视口高度,优化用户体验

/**
 * @method lazyLoad
 * @param {NodeList} $imgList      图片元素集合
 * @param {number}   preloadHeight 预加载高度
 */
export function lazyLoad($imgList, preloadHeight = 1000) {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) { // 目标元素出现在 root 可视区,返回 true
        const $target = entry.target
        const src = $target.getAttribute('lazyload')

        if (src) {
          $target.setAttribute('src', src) // 真正加载图片
        }
        observer.unobserve($target) // 解除观察
      }
    })
  }, {
    rootMargin: `0px 0px ${preloadHeight}px 0px`,
  })

  Array.prototype.forEach.call($imgList, ($item) => {
    if ($item.getAttribute('src')) return // 过滤已经加载过的图片
    observer.observe($item) // 开始观察
  })
}

使用方法:

// 图片元素设置 lazyload 属性
<img lazyload="图片链接" alt="图片说明">

// 观察图片元素
lazyLoad(document.querySelectorAll("[lazyload]"))

5. 元素吸顶、吸底

如果页面结构比较简单可以直接使用 css 粘性布局。

IntersectionObserver 实现元素固定思路也很简单,首先需要给固定元素包一层父元素,父元素指定高度占位,防止固定元素吸附时页面抖动,然后观察父元素的可视状态变化,当父元素即将离开可视区域时改变固定元素的样式。

/**
 * @method fixBanner
 * @param {HTMLElement} $observeEle 观察元素
 * @param {HTMLElement} $fixEle     固定定位元素
 */
export function fixBanner($observeEle, $fixEle) {
  const $ele = $fixEle
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        $ele.style.cssText = ''
      } else {
        $ele.style.cssText = 'position: fixed; top: 0; left: 0'
      }
    })
  }, {
    threshold: 1, // threshold 设置为 1 表示目标元素完全可见时触发回调函数
  })

  observer.observe($observeEle) // 开始观察
}

6. 加载更多

IntersectionObserver 实现加载更多需要在列表后面增加一个尾部元素(比如加载更多动画),当尾部元素进入可视区域就加载更多数据,注意尾部元素一定要一直处于所有列表元素的后面。

提前加载高度不能随意设置,如果设置太大会导致尾部元素一直处于可视状态。

function loadMore() {
  const observer = new IntersectionObserver(
    (entries) => {
      const loadingEntry = entries[0]

      if (loadingEntry.isIntersecting) {
        // 请求数据并插入列表
      }
    },
    {
      rootMargin: '0px 0px 600px 0px', // 提前加载高度
    },
  )

  observer.observe(document.querySelector('.mod_loading')) // 观察尾部元素
}

总结 

到此这篇关于js监听元素是否出现在可视区域(IntersectionObserver)的文章就介绍到这了,更多相关js监听元素出现可视区域内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文