前端API: IntersectionObserver的那一二三件事

IntersectionObserver 基础

IntersectionObserver 可以监听一个元素和可视区域相交部分的比例,然后在可视比例达到某个阈值的时候触发回调。比如可以用来处理图片的懒加载等等

首先我们来看下基本的格式:

const observer = new IntersectionObserver(callback, [options]);

相关的API属性和方法:

直接看他的Typescript结构吧

interface IntersectionObserver {
    // root 属性用来获取当前 intersectionObserver 实例的根元素
    readonly root: Element | Document | null;
   
    readonly rootMargin: string;
    
    readonly thresholds: ReadonlyArray<number>;
    
    disconnect(): void;
   
    observe(target: Element): void;
   
    takeRecords(): IntersectionObserverEntry[];
    
    unobserve(target: Element): void;
}

root: 如果构造函数未传入 root 或其值为null,则默认使用顶级当前文档的视口。

rootMargin : 是 IntersectionObserver 构造函数的一个可选属性,它定义了一个矩形区域,用于扩展或缩小root元素的可视区域,从而影响intersectionRatio的计算

const observer = new IntersectionObserver(
  entries => {
    // 处理entries
  },
  {
    root: document.querySelector('#scrollArea'), // 根元素 || 顶级当前文档
    rootMargin: '50px 20px 30px 10px' // 上右下左
  }
);

thresholds:,它定义了一个监听交叉变化时触发回调的阈值列表。这些阈值是介于0和1之间的数值,包括0和1,表示目标元素与根元素相交的比例。举个例子,当创建一个IntersectionObserver实例时,你可以指定一个或多个阈值。例如,如果你想要在目标元素至少有25%、50%和75%可见时触发回调,你可以这样设置thresholds

const observer = new IntersectionObserver(
  entries => {
    // 处理entries
  },
  {
    thresholds: [0, 0.25, 0.5, 0.75, 1]
  }
);

disconnect用于停止监听目标元素与根元素的交叉变化。当你不再需要观察元素的可见性变化时,可以调用disconnect方法来停止IntersectionObserver的所有活动。

调用disconnect方法后,IntersectionObserver将不再触发任何回调,即使目标元素的可见性发生变化。这意味着,你已经不再对目标元素的可见性感兴趣,或者你想要在组件卸载时清理资源。

// 创建一个IntersectionObserver实例
const observer = new IntersectionObserver(function(entries) {
  // 处理交叉变化
  entries.forEach(function(entry) {
    if (entry.isIntersecting) {
      console.log('元素现在可见');
    } else {
      console.log('元素不再可见');
    }
  });
});

// 开始观察一个元素
const target = document.querySelector('#my-element');
observer.observe(target);

// ...一段时间后...

// 停止观察元素
observer.disconnect();

observer: 用于开始监听一个目标元素与根元素的交叉变化。当你想要知道一个元素是否进入了视口(即用户的可见区域)时,你可以使用observe方法来指定需要观察的元素

// 创建一个IntersectionObserver实例
const observer = new IntersectionObserver(function(entries) {
  // 处理交叉变化
  entries.forEach(function(entry) {
    if (entry.isIntersecting) {
      console.log('元素现在可见');
    } else {
      console.log('元素不再可见');
    }
  });
});

// 获取要观察的元素
const target = document.querySelector('#my-element');

// 开始观察元素
observer.observe(target);

takeRecords:用于获取并清空IntersectionObserver实例的记录队列。这个方法返回一个IntersectionObserverEntry对象的数组,每个对象描述了目标元素的相交状态

unobserve:用于停止监听特定目标元素与根元素的交叉变化。当你不再需要监听某个元素的可见性变化时,你可以使用unobserve方法来停止对该元素的观察。

综合案例,实现图片的懒加载

下面的方法使用的react,可以做必要的安装哦!

下面是一个设置一个组件,看如下代码

/*
 * @Date: 2024-05-28 09:59:48
 * @Description: 组件的设计
 */
import { CSSProperties, FC, ReactNode, useEffect, useRef, useState } from "react";

interface MyLazyloadProps {
  className?: string; /* className 和 style 是给外层 div 添加样式的 */
  style?: CSSProperties;
  placeholder?: ReactNode; /* 是占位的内容 */
  offset?: string | number; /* 是距离到可视区域多远就触发加载 */
  width?: number | string;
  height?: string | number;
  onContentVisible?: () => void; /* 进入可视化区域后所产生的回调 */
  children: ReactNode;
}

const MyLazyload: FC<MyLazyloadProps> = (props) => {
  const { className = "", style, offset = 0, width, onContentVisible, placeholder, height, children } = props;

  const containerRef = useRef<HTMLDivElement>(null);
  const [visible, setVisible] = useState(false);

  const elementObserver = useRef<IntersectionObserver>();

  /* 关键函数去判断可视范围 */
  const lazyLoadHandler = (entries: IntersectionObserverEntry[]) => {

    const [entry] = entries;
    const { isIntersecting, intersectionRatio } = entry;
    
    if (intersectionRatio > 0) {
      const node = containerRef.current;
      console.log(node, entry, intersectionRatio);
    }

    if (isIntersecting) {
      setVisible(true);
      /* 可以通过这一层函数传递给外部,然后通过这个函数,可以在外部组件做相对应的处理等等 */
      onContentVisible?.();

      const node = containerRef.current;
      // 展示完成后及时的销毁
      if (node && node instanceof HTMLElement) {
        elementObserver.current?.unobserve(node);
      }
    }
  }

  useEffect(() => {
    const options = {
        /* 这边没有写root,则这边的根元素就是此文档的 containerRef */
        /* rootMargin 这边做了一次偏移处理 */
        rootMargin: typeof offset === 'number' ? `${offset}px` : offset || '0px',
        /* 设置 threshold 为 0 也就是一进入可视区域就触发 */
        threshold: 0,
    }

    elementObserver.current = new IntersectionObserver(lazyLoadHandler, options);

    const node = containerRef.current; // 拿到node

    if (node instanceof HTMLElement) {
        elementObserver.current.observe(node);
    }
    return () => {
        if (node && node instanceof HTMLElement) {
            elementObserver.current?.unobserve(node);
        }
    }
  }, []);

  const styles = { height, width, ...style };

  return (
    <div ref={containerRef} className={`${className}`} style={styles}>
      {visible ? children : placeholder}
    </div>
  );
};

export default MyLazyload;


组件的调用:

/*
 * @Date: 2024-05-27 11:21:07
 * @Description: 组件的调用
 */
import { useState } from "react";
import img1 from "./素材1.png";
import img2 from "./扑克牌1.jpg";
import "./App.css";
// import LazyLoad from 'react-lazyload';
import LazyLoad from "./MyLazyLoad";

function App() {
  const [isVisible, setIsVisible] = useState<boolean>(false);
  return (
    <div>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      <p>一一一一一一一一一一一一一一一一一一</p>
      {/* 这边增加一些类名可以做一些的动画 */}
      <LazyLoad
        className={isVisible ? "show" : "hide"}
        placeholder={<div>loading...</div>}
        onContentVisible={() => {
          console.log("comp visible");
          setIsVisible(true);
        }}
      >
        {/* <img src={img1}/> */}
      </LazyLoad>
      <LazyLoad
        placeholder={<div>loading...</div>}
        onContentVisible={() => {
          console.log("img visible");
        }}
      >
        <img src={img2} />
      </LazyLoad>
    </div>
  );
}

export default App;

我们看最后的效果:

当刚进入页面的时候,我们下面的元素都处于 loading中,也是上面的placeholder的占位内容。

在这里插入图片描述

当滑动图片的位置的时候才加载出相对应的图片地址和对应的类名

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/656250.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQLServer2012实例下某个数据库处于恢复挂起状态

由于机房电源线路故障&#xff0c;导致部分服务器飞正常状态下关机&#xff0c;电源线路重新恢复后&#xff0c;启动服务器后实例下有个数据库都显⽰“恢复挂起”状态&#xff0c;应用程序也⽆法对数据库的正常访问操作。 1、解决关键⽅法&#xff1a; run DBCC CHECKDB on t…

gin框架精通篇(二)

原生数据库使用 导入模块&#xff1a;go get -u github.com/go-sql-driver/mysql 安装 mysql 数据库 安装数据库可能遇到的问题&#xff1a;&#xff08;网上的方法基本可以解决&#xff09; ERROR 1045 (28000): Access denied for user ‘-root’‘localhost’ (using passwo…

ROS基础学习-话题通信机制研究

研究ROS通信机制 研究ROS通信机制 0.前言1.话题通信1.1 理论模型1.2 话题通讯的基本操作1.2.1 C++1.2.2 Python中使用自己的虚拟环境包1.2.2.1 参考11.2.2.2 参考21.2.2.3 /usr/bin/env:“python”:没有那个文件或目录1.2.3 Python1.2.2.1 发布方1.2.2.2 订阅方1.2.2.3 添加可执…

在 GPT-4o 释放完整能力前,听听实时多模态 AI 创业者的一手经验 | 编码人声

「编码人声」是由「RTE开发者社区」策划的一档播客节目&#xff0c;关注行业发展变革、开发者职涯发展、技术突破以及创业创新&#xff0c;由开发者来分享开发者眼中的工作与生活。 5 月中旬 GPT-4o 的发布&#xff0c;让人与 AI 的交互&#xff0c;从对话框的文本交流加速推进…

《Ai学习笔记》自然语言处理 (Natural Language Processing):常见机器阅读理解模型(上)02

Glove 词向量&#xff1a; 在机器理解中的词的表示&#xff1a; 词袋&#xff08;bow,bag of words&#xff09; one-hot 词向量 word2vec glove 目的&#xff1a;将一个词转换成一个向量 Word2vec 是一种用于生成词向量的工具包&#xff0c;由Google在2013年开源推出…

AI视频换脸!最快的方法,100%成功,完全免费,无需配置、打开即用

这是一款百分百完全免费&#xff0c;超级好用又简单的AI视频换脸工具&#xff0c;不仅效果非常不错而且支持CPU和GPU解码&#xff0c;即使电脑上没有独立显卡&#xff0c;你也可以通过电脑上的CPU要进解码&#xff0c;虽然我之前给他介绍好几个有关AI视频&#xff0c;比如像这个…

css 渐变色边框

效果图&#xff1a; 代码&#xff1a; <style>:root{--br-radius: 12px;}.list{position: relative;}.list_tle{margin-top: 15px;margin-bottom: 5px;}.item{position: relative;display: inline-flex;} .br1 {padding: 10px 16px;clip-path: inset(0 round 6px);borde…

kafka3.6.1版本学习

kafka目录结构 bin linux系统下可执行脚本文件 bin/windows windows系统下可执行脚本文件 config 配置文件 libs 依赖类库 licenses 许可信息 site-docs 文档 logs 服务日志 启动ZooKeeper 进入Kafka解压缩文件夹的config目录&#xff0c;修改zookeeper.properties配置文件 #t…

Sqoop的安装与测试

这里写目录标题 什么是Sqoop?Sqoop的安装与配置安装测试 什么是Sqoop? Sqoop就是hadoop和mysql的一个中间介质 , 作用就是可以将hadoop中的数据传到mysql中 , 或将mysql中的数据导入到hadoop中 Sqoop的安装与配置 安装 详细代码 //解压安装 [roothadoop soft]# tar -zxv…

【光伏干货】光伏无人机巡检步骤

随着光伏产业的迅速发展和无人机技术的日益成熟&#xff0c;光伏无人机巡检已成为提高光伏电站运维效率、降低运维成本的重要手段。本文将详细介绍光伏无人机巡检的步骤&#xff0c;帮助读者更好地理解和应用这一技术。 一、前期准备 1、设备检查&#xff1a;对无人机及其相关…

13 VUE学习:组件v-model

基本用法 v-model 可以在组件上使用以实现双向绑定。 从 Vue 3.4 开始&#xff0c;推荐的实现方式是使用 [defineModel()]宏&#xff1a; <!-- Child.vue --> <script setup> const model defineModel()function update() {model.value } </script><te…

我的心情JSP+Servlet+JDBC+MySQL

系统概述 本系统采用JSPServletJDBCMySQL技术进行开发&#xff0c;包括查看我的心情列表&#xff0c; 编辑我的心情信息、新增我的心情。使用方法 将项目从idea中导入&#xff0c;然后配置项目的结构&#xff0c;包括jdk,库&#xff0c;模块&#xff0c;项目&#xff0c;工件…

分支机构多,如何确保文件跨域传输安全可控?

随着企业全球化发展&#xff0c;分支机构的分布越来越广泛&#xff0c;跨域文件传输需求也随之增加。然而&#xff0c;跨域文件传输面临的数据安全和传输效率问题&#xff0c;使得构建一个安全、可控的文件交换系统成为迫切需求。FileLink跨网文件交换系统通过综合的技术手段和…

开发者的福音:免去搭建服务,让你的应用开发变得像吃蛋糕一样简单!

传统应用开发的"噩梦" 想象一下&#xff0c;你正在准备一场盛大的晚宴&#xff0c;但必须从零开始建造厨房、种植食材、甚至学习烹饪技巧。这就是传统应用开发的现状——你不仅要设计数据库、编写API接口&#xff0c;还要处理对象存储、实时数据库、云数据库等一系列…

图卷积神经网络的简史 及其与卷积神经网络的异同

图卷积神经网络&#xff08;GCN&#xff09;已经在处理图结构数据方面取得了巨大的成功。在本小节中&#xff0c;我们将深入探讨图卷积神经网络的起源、发展历程&#xff0c;并提供一个简单的Python代码实现示例&#xff0c;以帮助读者更好地理解这一概念。 图卷积神经网络的简…

分类内按规则拆分一行变多行

Excel的A列是分类列&#xff0c;B列是由">"连接起来的多个字符串&#xff0c;可以看成是合并后的明细&#xff1a; AB1IDRule: Condition2470210642217Test3470251569449Doors & Hardware > Door Jambs> 119mm4470251602217Bathroom > Stone Tops &…

Jmeter元件及基本作用域

&#x1f680;从今天开始学习性能测试工具——Jmeter&#xff0c;小梦也是先学习了下Jmeter的元件概念以及其基本的作用域&#xff0c;整理了下笔记&#xff0c;希望不管是从事开发领域还是测试领域的朋友们&#xff0c;我们一起学习下Jmeter工具&#xff0c;提升工作中的技能&…

TikTok电商带货特训营,跟随时代潮流,跨境掘金(8节课)

课程内容&#xff1a; 1-先导课 2-一、店铺运营认知与思路 3-二、店铺风控注意事项 4-三、美区Tiktok前期工作-1店铺入驻模式 5-三、美区Tiktok前期工作-2指纹浏览器介绍 6-三、美区Tiktok前期工作-4绑定电话号码 7-三、美区Tiktok前期工作-5添加仓库地址 8-三、美区Ti…

【LabVIEW FPGA入门】同步C系列模块

1.同步使用循环定时器VI计时循环速率的系列模块 数字模块SAR ADC 模块多路复用模块 数字通道可以在一个时钟周期内执行。模拟通道需要多个时钟周期。 同步模拟模块的每个通道有一个 ADC&#xff0c;采集的数据在通道之间没有明显的偏差。多路复用模块使用多路复用器通过单个 A…

苹果与OpenAI合作在即:iOS 18中的ChatGPT引发期待与担忧

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…