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

news2024/11/21 1:47:27

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的占位内容。

在这里插入图片描述

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue 笔记02

目录 01 事件修饰符 02 按键修饰符 03 v-bind属性 04 vue-axios的基本使用 05 vue的生命周期 06 vue生命周期涉及到的其他的知识点 01 事件修饰符 vue的事件修饰符 事件名称.修饰符1.修饰符2...事件驱动函数 stop 阻止冒泡修饰符 prevent 阻止默认行为 once 当前事件只触…

牛客题霸-SQL大厂面试真题(一)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 由于涉及到的数据库表较多&#xff0c;因此本文不再展示&#xff0c;只提供 MySQL 代码与示例输出。 以下内容是…

期权方向性交易策略怎么制定?

今天期权懂带你了解期权方向性交易策略怎么制定&#xff1f;国内的期权品种已经多达十几种&#xff0c;其中ETF期权是流量最大的品种&#xff0c;截止今日已经上市了十二种ETF期权。 期权方向性交易策略怎么制定&#xff1f; 期权方向性交易策略主要依赖于投资者对市场未来走势…

作业job——kettle开发30

一、作业 大多数ETL项目都需要完成各种各样的维护工作。 例如&#xff0c;如何传送文件;验证数据库表是否存在&#xff0c;等等。而这些操作都是按照一定顺序完成。因为转换以并行方式执行&#xff0c;就需要一个可以串行执行的作业来处理这些操作。 一个作业包含一个或多个作…

WHLUG活动回顾 | 4大技术分享!干货满满,热闹非凡!

内容来源&#xff1a;deepin&#xff08;深度&#xff09;社区 2024 年 5 月 25 日下午&#xff0c;由 deepin&#xff08;深度&#xff09;社区华中科技大学开放原子开源俱乐部联合举办的武汉 Linux 爱好者线下沙龙活动&#xff08;WHLUG&#xff09;在华中科技大学成功举办。…

vue3中的toRaw API

文章目录 什么是toRaw API&#xff1f;为什么需要toRaw&#xff1f;如何使用toRaw&#xff1f;实际应用场景 这两天在写项目的时候&#xff0c;发现了一个之前没用过的api&#xff0c;于是上网查了一下&#xff0c;发现这个api还是挺常用&#xff0c;所以在这记录一下 什么是t…

Android11 事件分发流程

在Android 11 输入系统之InputDispatcher和应用窗口建立联系一文中介绍到&#xff0c;当InputDispatcher写入数据后&#xff0c;客户端这边就会调用handleEvent方法接收数据 //frameworks\base\core\jni\android_view_InputEventReceiver.cpp int NativeInputEventReceiver::h…

springboot项目war包部署到腾讯云服务器

一、购买服务器 试用 1 个月&#xff08;需要实名和人脸验证&#xff09; 云产品免费体验馆_云产品免费试用_个人云产品试用-腾讯云 重置密码 登录以后 二、云服务器安装MySql 登录后&#xff0c;接下来的一切我们使用linux命令来操作。 1、卸载centos默认安装的mariadb rp…

axios和ts的简单使用

按照官网的使用案例简单记下笔记 1&#xff1a;安装 npm install axios 2&#xff1a;案例 一个简单的config配置信息 // 发起一个post请求 axios({method: post,url: /user/12345,data: {firstName: Fred,lastName: Flintstone} }); case // 在 node.js 用GET请求获取…

有哪些藏文翻译器在线翻译?工具分享

有哪些藏文翻译器在线翻译&#xff1f;随着全球化的推进&#xff0c;语言之间的交流变得越来越重要。藏语作为中华民族的重要语言之一&#xff0c;其翻译需求也日益增加。为了满足这一需求&#xff0c;市场上涌现出了多款藏文翻译器在线翻译工具&#xff0c;它们以其高效、准确…

Qt for android : libusb在android中使用

简介 如何在Qt for Android中使用libusb&#xff0c; 其实libusb的文档里面都写的很清楚&#xff0c; 这里只是稍微做下整理。 libusb libusb github源码 libusb release的版本, 有编译好的静态 步骤 1. 下载libusb libusb v1.0.027 源码包 2. 整理提取libusb android使用源…

怎么使用Stable diffusion中的models

Stable diffusion中的models Stable diffusion model也可以叫做checkpoint model&#xff0c;是预先训练好的Stable diffusion权重&#xff0c;用于生成特定风格的图像。模型生成的图像类型取决于训练图像。 如果训练数据中从未出现过猫的图像&#xff0c;模型就无法生成猫的…

【MySQL数据库】 MySQL主从复制

MySQL主从复制 MySQL主从复制主从复制与读写分离的意义主从数据库实现同步&#xff08;主从复制&#xff09;三台mysql服务器搭建主从复制&#xff0c;要求不可以用root帐号同步&#xff0c;要求第三台服务器在测试过1、2的主从复制之后进行主从复制配置 MySQL主从复制 主从复…

FastAPI - 组织模块2

FastAPI没有强制指定某种格式来组织项目结构&#xff0c;开发者可以根据自己喜好和项目需要来定制自己的项目结构。 https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/ 在项目根目录创建python包routers&#xff0c;然后创建member.py文件 member.py文件内容 …

嘴尚绝卤味:健康美味新选择,开启味蕾新旅程!

在这个美食文化繁荣的时代&#xff0c;卤味作为传统小吃界的一颗璀璨明珠&#xff0c;一直深受大众的喜爱。而今天&#xff0c;我要向大家介绍一款不仅美味可口&#xff0c;更注重健康营养的卤味品牌——嘴尚绝卤味。它以其独特的制作工艺和丰富的口感&#xff0c;成为众多卤味…

滚珠花键在工业自动化领域中有什么优势?

滚珠花键是工业自动化设备中重要的传动系统之一&#xff0c;不仅在工业自动化系统中有着广泛的运用&#xff0c;还在机械制造领域、航空航天领域、工业汽车领域、工业机器人、高速铁路、新能源领域 等都得到广泛应用。由于具有高精度、高承载、耐磨损、传递扭矩大等特点&#x…

EE trade:如何理解做空黄金

理解做空黄金&#xff0c;其实就是理解卖空操作在黄金市场中的应用。卖空&#xff0c;或称为做空&#xff0c;是指投资者预测某资产(在这个例子中是黄金)的价格会下跌&#xff0c;因此采取的一种投资策略。 下面简要说明做空黄金的过程和相关概念&#xff1a; 借入黄金: 首先…

饲料粉碎混合机组:打造精细化养殖

饲料粉碎混合机组是畜牧业和养殖业中不可或缺的设备。它集饲料粉碎和混合于一体&#xff0c;可以高效地处理各种饲料原料&#xff0c;提高饲料的均匀度和营养价值。 具体来说&#xff0c;饲料粉碎混合机组的主要功能包括将饲料原料进行粉碎&#xff0c;增加其表面积和调质粒度…

计算机毕业设计python+spark天气预测 天气可视化 天气大数据 空气质量检测 空气质量分析 气象大数据 气象分析 大数据毕业设计 大数据毕设

摘 要 近些年大数据人工智能等技术发展迅速&#xff0c;我国工业正努力从“制造”迈向“智造”实现新跨越。神经网络(NeuronNetwork)是一种计算模型&#xff0c;通过大量数据的学习&#xff0c;来发现数据之间的模式和规律&#xff0c;模仿人脑神经元的工作方式。随着算力的提…

SEC突发:以太坊ETF大概率获批

美国证监会大概率批准以太坊现货ETF。 5月20日&#xff0c;据外媒CoinDesk报道&#xff0c;知情人士透露&#xff0c;美国SEC周一要求证券交易所更新以太坊现货ETF的19b-4备案文件。19b-4备案文件是一种表格&#xff0c;用于向SEC通报允许基金在交易所交易的规则变更。 三位消息…