JavaScript API: IntersectionObserver

简介

IntersectionObserver 是一个 JavaScript API,用于监测一个元素与其父元素或视窗的交叉状态。它可以用来判断一个元素是否可见或者在视窗中的位置是否发生变化。

使用 IntersectionObserver,你可以注册一个回调函数,当被观察的元素进入或离开视窗,或者与其父元素发生交叉时,该回调函数将被触发。这个 API 提供了一种高效的方法来监测元素的可见性,尤其在处理滚动事件时非常有用。

通过 IntersectionObserver,你可以实现一些常见的功能,例如延迟加载(当元素进入视窗时再加载内容)、无限滚动(滚动到底部时加载更多内容)以及元素的懒加载(当元素进入视窗时再加载真实内容,而不是占位符)等。它能够帮助你提高页面性能,减少不必要的资源加载,以及改善用户体验。

总结来说,IntersectionObserver 是一个用于监测元素可见性和位置变化的 API,可以实现一些常见的交互效果和性能优化。

具体内容见官方文档:https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver

下面说两个简单的应用案例

案例一:滚动动画

在这里插入图片描述

<template>
  <div id="abc">
    <div class="observer-item">content-1</div>
    <div class="observer-item">content-2</div>
    <div class="observer-item">content-3</div>
    <div class="observer-item">content-4</div>
    <div class="observer-item">content-5</div>
    <div class="observer-item">content-6</div>
    <div class="observer-item">content-7</div>
    <div class="observer-item">content-8</div>
    <div class="observer-item">content-9</div>
    <div class="observer-item">content-10</div>
    <div class="observer-item">content-11</div>
    <div class="observer-item">content-12</div>
    <div class="observer-item">content-13</div>
    <div class="observer-item">content-14</div>
    <div class="observer-item">content-15</div>
  </div>
</template>

<script setup lang="ts">
import { onMounted } from "vue";

onMounted(() => {
  // 获取所有的元素
  const elements = document.querySelectorAll(".observer-item");
  console.log(elements.length);

  // 使用IntersectionObserver 来检测子元素与父元素的交叉状态
  const observer = new IntersectionObserver(callback);
  elements.forEach((ele) => {
    ele.classList.add("opaque");
    // 观察元素
    observer.observe(ele);
  });

  function callback(entries, instance) {
    entries.forEach((entry) => {
      // 判断元素是否出现在父元素中
      // 每个对象表示一个目标元素与父元素或视窗的交叉状态信息,包括目标元素的位置、大小、可见性等
      if (entry.isIntersecting) {
        const element = entry.target;
        element.classList.remove("opaque");
        element.classList.add("come-in");
        instance.unobserve(element);
      }
    });
  }
});
</script>

<style scoped>
#abc {
  width: 400px;
  height: 300px;
  border: 1px solid red;
  overflow-y: scroll;
  margin-left: 500px;
}
.observer-item {
  width: 100%;
  height: 100px;
  line-height: 100px;
  margin-bottom: 20px;
}
.observer-item:nth-child(odd) {
  background-color: pink;
}
.observer-item:nth-child(even) {
  background-color: skyblue;
}
.opaque {
  opacity: 0;
}
.come-in {
  opacity: 1;
  transform: translateY(150px);
  animation: come-in 1s ease forwards;
}
.come-in:nth-child(odd) {
  animation-duration: 1s;
}
@keyframes come-in {
  100% {
    transform: translateY(0);
  }
}
</style>

案例二:无限滚动(滚动到底部时加载更多内容)

这个应用应该更广泛一点,原来判断是否滚动到底的话一般是采用下面这种方案

<script>
  window.onload = () => {
    // 基本思路
    // 滚动体条所能滚动的最大高度 + continer的高度 = 子盒子(item)的高度;
    const container = document.querySelector(".container");
    console.dir(container);
    const item = document.querySelector(".item");
    container.addEventListener("scroll",() => {
        // 父盒子的高度
       const clientHeight = container.clientHeight;
       // 子盒子的高度(滚动盒子的高度)
       const scrollHeight = container.scrollHeight;
       // 滚动的最大距离
       const scrollHeight_clientHeight = scrollHeight - clientHeight;
       // 实时滚动距离
       const scrollTop = container.scrollTop;
       // 滚动的最大距离小于等于实时滚动距离时,滚动到了底部
        if(scrollHeight_clientHeight <= scrollTop){
            console.log("滚动到底部");
        }
    })
  };
</script>

现在的话可以通过IntersectionObserver 来实现,基本思路是:

  • 创建一个 IntersectionObserver 实例,指定观测的根元素(滚动容器)和阈值(thresholds)。
  • 将最后一个加载元素作为观测目标,调用 IntersectionObserverobserve 方法开始观测。
  • IntersectionObserver 的回调函数中,当最后一个加载元素与容器底部交叉时,触发加载更多的操作。
  • 加载更多的操作可以是异步请求数据,更新页面内容等。
  • 在加载完成后,更新最后一个加载元素的位置,继续观测。

在这里插入图片描述
在这里插入图片描述

<template>
  <div v-loading="loading">
    <div id="abc">
      <div v-for="item in list" :key="item" class="observer-item">
        content-{{ item }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";

const list = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const loading = ref(false);
const lastElement = ref();

onMounted(() => {
  // 使用IntersectionObserver 来检测子元素与父元素的交叉状态
  const observer = new IntersectionObserver(callback);
  // 观察最后一个元素
  lastElement.value = document.querySelector(".observer-item:last-child");
  // 观察元素
  observer.observe(lastElement.value);

  function callback(entries, instance) {
    entries.forEach((entry) => {
      // 判断元素是否出现在父元素中
      if (entry.isIntersecting) {
        const target = entry.target;
        console.log("滚动到底了:", target);
        // 加载新数据
        // 取消上一个元素的观察
        instance.unobserve(lastElement.value);
        if (list.value.length < 15) {
          loading.value = true;
          list.value.push(...[11, 12, 13, 14, 15]);
          setTimeout(() => {
            // 更新新的观察对象
            lastElement.value = document.querySelector(
              ".observer-item:last-child"
            );
            observer.observe(lastElement.value);
            loading.value = false;
          }, 1000);
        }
      }
    });
  }
});
</script>

<style scoped>
#abc {
  width: 400px;
  height: 300px;
  border: 1px solid red;
  overflow-y: scroll;
  margin-left: 500px;
}
.observer-item {
  width: 100%;
  height: 100px;
  line-height: 100px;
  margin-bottom: 20px;
}
.observer-item:nth-child(odd) {
  background-color: pink;
}
.observer-item:nth-child(even) {
  background-color: skyblue;
}
</style>

优点

<template>
  <div v-loading="loading">
    <div id="abc">
      <div v-for="item in list" :key="item" class="observer-item">
        content-{{ item }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";

const list = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const loading = ref(false);
const lastElement = ref();

onMounted(() => {
  // 使用IntersectionObserver 来检测子元素与父元素的交叉状态
  const observer = new IntersectionObserver(callback);
  // 观察最后一个元素
  lastElement.value = document.querySelector(".observer-item:last-child");
  // 观察元素
  observer.observe(lastElement.value);

  function callback(entries, instance) {
    entries.forEach((entry) => {
      // 判断元素是否出现在父元素中
      if (entry.isIntersecting) {
        const target = entry.target;
        console.log("滚动到底了:", target);
        // 加载新数据
        // 取消上一个元素的观察
        instance.unobserve(lastElement.value);
        if (list.value.length < 15) {
          loading.value = true;
          list.value.push(...[11, 12, 13, 14, 15]);
          setTimeout(() => {
            // 更新新的观察对象
            lastElement.value = document.querySelector(
              ".observer-item:last-child"
            );
            observer.observe(lastElement.value);
            loading.value = false;
          }, 1000);
        }
      }
    });
  }
});
</script>

<style scoped>
#abc {
  width: 400px;
  height: 300px;
  border: 1px solid red;
  overflow-y: scroll;
  margin-left: 500px;
}
.observer-item {
  width: 100%;
  height: 100px;
  line-height: 100px;
  margin-bottom: 20px;
}
.observer-item:nth-child(odd) {
  background-color: pink;
}
.observer-item:nth-child(even) {
  background-color: skyblue;
}
</style>

兼容性

在这里插入图片描述

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

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

相关文章

ChatGPT生成的docx文档压缩Python代码

对DOCX文件中的图片进行缩小处理 这份Python脚本旨在处理给定的DOCX&#xff08;Word文档&#xff09;文件中的图片&#xff0c;将其按照指定的比例进行缩小&#xff0c;并生成一个新的压缩版DOCX文件&#xff0c;其中包含经过缩小处理的图片。 代码功能概览&#xff1a; 导入…

.NET如何调用Web Service服务?

我们知道&#xff0c;现在用Web Service提供对外接口的项目其实很少了&#xff0c;现在大部分应用都是b/s端的了&#xff0c;WebApi的优势自然而然就体现出来了&#xff0c;可自定义请求头部信息、可对数据进行缓存、使用json字符串让开发更加灵活。那么Web Service是不是就无用…

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

元宇宙&#xff0c;是一个虚拟的网络世界&#xff0c;它与现实世界相互连接&#xff0c;为人们提供了一个身临其境的数字体验。元宇宙的概念并不新鲜&#xff0c;早在上个世纪就有科幻作家和电影导演对它进行了想象和创造。但是&#xff0c;随着科技的发展&#xff0c;特别是5G…

2023最新大模型实验室解决方案

人工智能是引领未来的新兴战略性技术&#xff0c;是驱动新一轮科技革命和产业变革的重要力量。近年来&#xff0c;人工智能相关技术持续演进&#xff0c;产业化和商业化进程不断提速&#xff0c;正在加快与千行百业深度融合。 大模型实验室架构图 大模型实验室建设内容 一、课…

编程应用实际场景:台球厅怎么样用电脑给客人计时,台球计时收费系统操作教程

一、前言 准确控制顾客在店内游玩的时间&#xff0c;从而控制店内的各项成本&#xff0c;并提升店内的客流量。在顾客享受计时项目的时候&#xff0c;可以同时添加其他食物消费&#xff0c;并将单据合并统一结账。软件中的会员功能可以为客户办理会员可以使用灯控器控灯&#…

GPT-4V 在保险行业的应用

在科技的进步中&#xff0c;人工智能与大数据技术的结合产生了巨大的能量&#xff0c;推动了各行各业的创新与变革。OpenAI&#xff0c;作为全球领先的人工智能研发机构&#xff0c;在今年的9月25日&#xff0c;以一种崭新的方式&#xff0c;升级了其旗下的GPT-4模型。这次的升…

程序员必备的十种排序算法

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

记录 | Google gtest安装

1、下载源码 git clone https://github.com/google/googletest2、源码编译 cd googletestcmake CMaakeLists.txtmake -j32编译成功后会在 googletest/lib 下生成 libgtest.a、libgtest_main.a、libgmock.a、libgmock_main.a 四个静态库。 把生成的静态库和头加入到系统环境…

提升测试工具开发的思考

本文针对测试部效率提升测试工具开发、管理、维护暴露出来的问题的一些思考以及一些个人改进观点。 写在前面 本文提到的效率提升测试工具不是指的部门中固有的自动化测试工具&#xff0c;这里提到的测试工具统一指测试人员在工作之余自主开发用于期望替代重复、繁琐、耗时的手…

Leetcode—709.转换成小写字母【简单】

2023每日刷题&#xff08;五十八&#xff09; Leetcode—709.转换成小写字母 实现代码 char* toLowerCase(char* s) {int len strlen(s);for(int i 0; i < len; i) {if(s[i] > A && s[i] < Z) {s[i] tolower(s[i]);}}return s; }运行结果 之后我会持续更…

竞赛保研 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

如何正确选择打造自己的私域流量知识付费平台,我有才知识付费saas平台告诉你!

在当今数字化时代&#xff0c;私域流量知识付费平台已经成为企业和个人获取收益、扩大影响力的重要渠道。但是&#xff0c;如何正确选择并打造一个属于自己的私域流量知识付费平台呢&#xff1f;我有才知识付费saas平台为你提供一站式解决方案&#xff01; 一、功能全面&#…

【个人经验】Overleaf 在 two-column 格式中 插入图片 插入代码

一、在 two-column 格式中插入图片的方法 1.1 将图片上传至image文件夹 1.2 起始位置处导入包&#xff0c;并将图片上传至image文件夹 % 新增&#xff1a;为导入图片 \usepackage{graphicx} %导入包 \graphicspath{ {image/} } %image为文件夹名&#xff0c;可以在左侧自己…

MetaAI发布Seamless:两秒内实现跨语言同声传译

在当今日益互联的世界中&#xff0c;语言差异常常成为沟通的障碍。MetaAI最新发布的语音翻译大模型Seamless&#xff0c;正是为打破这一障碍而生。Seamless不仅提供流畅、高效的多语言翻译功能&#xff0c;更在保留说话人韵律和风格方面取得突破&#xff0c;是AI同声传译领域的…

harmonyos预览功能报错:[webpack-cli] SyntaxError: Unexpected end of JSON input

harmonyos预览功能报错 在使用DevEco Studio写页面&#xff0c;进行预览的时候报错&#xff1a; [Compile Result] [webpack-cli] SyntaxError: Unexpected end of JSON input [Compile Result] at JSON.parse (<anonymous>) [Compile Result] at updateCached…

CH03_生成实例

Singleton模式 单例模式&#xff08;Singleton&#xff09;&#xff0c;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 类图 说明 Singleton 在Singleton模式中&#xff0c;只有Singleton这一个角色。Singleton角色中有一个返回唯一实例的static方法。该…

使用Visual Studio(VS)创建空项目的Win32桌面应用程序【main函数入口变WinMain】

前言 在Visual Studio中直接新建Windows桌面应用程序会有很多多余的代码生成&#xff0c;本文将提供从空项目创建Win32项目的方法&#xff0c;解决新建空项目直接使用WinMain代码编译报错的问题 例如&#xff1a;LNK2019 &#xff1a;无法解析的外部符号 参考博客&#xff1…

kafka 详细介绍

目录 前言 分布式架构&#xff1a; 消息发布-订阅模型&#xff1a; 持久性存储&#xff1a; 分区和副本&#xff1a; 水平扩展&#xff1a; 高性能&#xff1a; 生态系统&#xff1a; 我的其他博客 前言 Kafka 是由 Apache 软件基金会开发的一种开源流处理平台&#xf…

常见的计算机图片格式

左rgb &#xff08;光源色彩&#xff09; 右cmyk &#xff08;印刷色彩&#xff09; 缺点&#xff0c;不能保存&#xff0c;储存空间太大

【概率方法】MCMC 之 Gibbs 采样

上一篇文章讲到&#xff0c;MCMC 中的 HM 算法&#xff0c;它可以解决拒绝采样效率低的问题&#xff0c;但是实际上&#xff0c;当维度高的时候 HM 算法还是在同时处理多个维度&#xff0c;以两个变量 x [ x , y ] \mathbf{x} [x,y] x[x,y] 来说&#xff0c;也就是同时从联合…