【前端】IntersectionObserver 实现图片懒加载和无限滚动

news/2024/7/7 20:23:26 标签: 前端, vue.js, javascript

前端】IntersectionObserver 实现图片懒加载和无限滚动

前端开发中,性能优化是一个重要的考量因素。随着现代网页和应用的复杂性增加,确保页面快速加载和流畅运行变得越来越重要。本文将介绍一种强大的工具——IntersectionObserver API,并结合 Vue 项目,讲解如何使用它来实现图片懒加载和无限滚动。
在这里插入图片描述

IntersectionObserver API 简介

IntersectionObserver API 是现代浏览器提供的一种异步观察者,它可以监视一个元素与视口(或某个特定祖先元素)交叉状态的变化。它的主要用途包括:

  • 图片懒加载
  • 无限滚动加载内容
  • 实现元素的延迟加载
  • 触发动画效果

IntersectionObserver 的基本用法

要使用 IntersectionObserver,首先需要创建一个 IntersectionObserver 实例,并传入一个回调函数和一些配置选项:

javascript">const observer = new IntersectionObserver(callback, options);
  • callback: 每当被观察的元素的可见性变化时,调用的回调函数。该函数接收两个参数:
    • entries: 被观察元素的列表,每个元素都是一个 IntersectionObserverEntry 对象。
    • observer: IntersectionObserver 实例本身。
  • options: 一个可选参数对象,用于配置观察器的行为。包括以下属性:
    • root: 用于观察的祖先元素,默认为视口。
    • rootMargin: 根元素的外边距,用于扩大或缩小根元素的判定区域。
    • threshold: 一个数组,规定在什么可见比例下触发回调。

回调函数

回调函数处理 IntersectionObserverEntry 对象的数组,每个对象包含了元素的交叉信息:

javascript">const callback = (entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 元素进入视口
      console.log('Element is in viewport:', entry.target);
      // 执行懒加载操作,如加载图片
      const img = entry.target;
      img.src = img.dataset.src;
      // 停止观察当前元素
      observer.unobserve(entry.target);
    }
  });
};

配置选项示例

javascript">const options = {
  root: null, // 默认为视口
  rootMargin: '0px', // 没有外边距
  threshold: 0.1 // 当 10% 的目标元素可见时触发回调
};

观察目标元素

创建 IntersectionObserver 实例后,可以使用 observe 方法来观察目标元素:

javascript">const img = document.querySelector('img');
observer.observe(img);

完整示例

以下是一个完整的示例,展示如何使用 IntersectionObserver 实现图片懒加载:

javascript">document.addEventListener('DOMContentLoaded', () => {
  const images = document.querySelectorAll('img[data-src]');

  const callback = (entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        observer.unobserve(img);
      }
    });
  };

  const options = {
    root: null,
    rootMargin: '0px',
    threshold: 0.1
  };

  const observer = new IntersectionObserver(callback, options);

  images.forEach(image => {
    observer.observe(image);
  });
});

更加深入的学习我推荐:阮一峰的帖子

在 Vue 项目中实现图片懒加载

接下来,我们将结合 Vue 项目,使用 IntersectionObserver 实现图片懒加载。首先,我们需要创建一个自定义指令 v-lazy

创建自定义指令

在 Vue 中,我们可以通过自定义指令来实现懒加载。以下是一个简单的实现:

javascript">Vue.directive('lazy', {
  inserted: function(el, binding) {
    let observer;
    if (IntersectionObserver) {
      observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            observer.unobserve(el);
            const src = binding.value;
            el.src = src;
          }
        });
      });
      observer.observe(el);
    } else {
      // 如果浏览器不支持 IntersectionObserver,需要提供一个降级方案
      el.src = binding.value;
    }
  }
});

在模板中使用指令

<template>
  <div>
    <img v-lazy="imageSource" alt="Lazy loaded image" />
  </div>
</template>

<script>javascript">
export default {
  data() {
    return {
      imageSource: 'path/to/image.jpg'
    };
  }
};
</script>

这样,当图片进入视口时,v-lazy 指令会触发加载图片,从而实现懒加载。

在 Vue 项目中实现无限滚动

除了图片懒加载,我们还可以使用 IntersectionObserver 实现无限滚动加载内容。以下是实现步骤:

创建无限滚动组件

javascript">Vue.component('infinite-scroll', {
  data() {
    return {
      items: [],
      page: 1,
      observer: null,
    };
  },
  mounted() {
    this.loadItems();
    this.createObserver();
  },
  methods: {
    loadItems() {
      // 模拟加载数据
      fetch(`https://api.example.com/items?page=${this.page}`)
        .then(response => response.json())
        .then(data => {
          this.items = [...this.items, ...data];
          this.page += 1;
        });
    },
    createObserver() {
      const options = {
        root: null,
        rootMargin: '0px',
        threshold: 1.0
      };

      this.observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            this.loadItems();
          }
        });
      }, options);

      this.$nextTick(() => {
        const sentinel = this.$refs.sentinel;
        this.observer.observe(sentinel);
      });
    }
  },
  template: `
    <div>
      <div v-for="item in items" :key="item.id" class="item">
        {{ item.name }}
      </div>
      <div ref="sentinel" class="sentinel"></div>
    </div>
  `
});

在主应用中使用组件

<template>
  <div id="app">
    <infinite-scroll></infinite-scroll>
  </div>
</template>

<script>javascript">
import InfiniteScroll from './components/InfiniteScroll.vue';

export default {
  components: {
    InfiniteScroll
  }
};
</script>

在这个示例中,当用户滚动到页面底部时,IntersectionObserver 会触发回调函数,加载更多数据并更新页面内容,从而实现无限滚动。


http://www.niftyadmin.cn/n/5536814.html

相关文章

软件测试面试题:Redis的五种数据结构,以及使用的场景是什么?

字符串&#xff08;Strings&#xff09;&#xff1a;简单直接&#xff0c;就像记事本一样&#xff0c;用来存储和快速访问简单的数据&#xff0c;比如缓存网页或者保存用户会话信息。 列表&#xff08;Lists&#xff09;&#xff1a;有序的数据集合&#xff0c;适合用来存储按…

油猴Safari浏览器插件:Tampermonkey for Mac 下载

Tampermonkey 是一个强大的浏览器扩展&#xff0c;用于运行用户脚本&#xff0c;这些脚本可以自定义和增强网页的功能。它允许用户在网页上执行各种自动化任务&#xff0c;比如自动填写表单、移除广告、改变页面布局等。适用浏览器&#xff1a; Tampermonkey 适用于多数主流浏览…

案例分享:数据集市搭建方案中集成SQLFlow数据血缘分析工具

本文中描述的数据集市搭建方案是一家跨国公司在AWS平台上的具体实践案例。我公司参与其中的数据血缘部分的建设&#xff0c;SQLFlow数据血缘分析工具在该方案中帮助用户实现了数据血缘分析。 用户使用Redshift 数据库仓库进行数据集市开发。从各种数据源提取数据&#xff0c;并…

openwrt 23.05.2 稳定版本 导入树莓派4B

openwrt 23.05.2 稳定版本 导入树莓派4B 强烈建议新手使用稳定版本 这里真的非常感谢这篇博客提供了大量支持&#xff0c;本文有大量篇幅抄袭。 https://blog.csdn.net/qq_44730817/article/details/135258664 编译系统&#xff08;Build system usage&#xff09; 下载源代…

秋招突击——设计模式补充——简单工厂模式和策略模式

文章目录 引言正文简单工厂模式策略模式策略模式和工厂模式的结合策略模式解析 总结 引言 一个一个来吧&#xff0c;面试腾讯的时候&#xff0c;问了我单例模式相关的东西&#xff0c;自己这方面的东西&#xff0c;还没有看过。这里需要需要补充一下。但是设计模式有很多&…

【机器学习】连续字段的特征变换

介绍 除了离散变量的重编码外&#xff0c;有的时候我们也需要对连续变量进行转化&#xff0c;以提升模型表现或模型训练效率。在之前的内容中我们曾介绍了关于连续变量标准化和归一化的相关内容&#xff0c;对连续变量而言&#xff0c;标准化可以消除量纲影响并且加快梯度下降…

论文浅尝 | 从最少到最多的提示可在大型语言模型中实现复杂的推理

笔记整理&#xff1a;王泽元&#xff0c;浙江大学博士 链接&#xff1a;https://openreview.net/forum?idWZH7099tgfM 1. 动机 尽管深度学习已经取得了巨大的成功&#xff0c;但它与人类智慧仍然存在一些明显差距。这些差距包括以下几个方面&#xff1a;1&#xff09;学习新任…

回溯法:生成一个字符串的所有排列组合

问题&#xff1a;字符串abcd怎样获取abcd、acbd、acdb、adbc、adcb、bacd、bcad、bdac、bdca、cabd、cdba、cadb、cbda等&#xff0c;所有排列。 使用回溯法来生成一个字符串的所有排列 import java.util.ArrayList; import java.util.List;public class Permutations {publi…