vue3封装Hooks 实现图片懒加载

一、引言

在现代 Web 开发领域,图片懒加载的重要性不容小觑。

首先,它对页面加载速度有着极大提升作用。当页面包含大量图片时,若不采用懒加载,所有图片会在页面初始化时一同请求加载,这会导致加载时间过长。而懒加载仅在图片进入浏览器可视区域时才触发加载,大大减少了初始加载的数据量,使关键资源(如 HTML、CSS 等)能优先高效加载,让用户更快看到页面布局并进行交互。

其次,能有效节省用户流量。对于移动用户或流量有限的情况,懒加载按需加载图片,避免了加载那些用户可能根本不会看到的图片,防止不必要的流量消耗。

二、图片懒加载原理概述

简单解释什么是图片懒加载。即图片在进入浏览器的可视区域时才进行加载,而不是在页面初始化时就全部加载所有图片。

可以用一些简单的示意图或者类比的方式(比如把页面想象成一个画展,只有当观众走到画作前才会仔细去看这幅画,也就是才加载这幅画的细节,类似图片进入可视区才加载)来帮助读者更好地理解懒加载的概念。

三、封装图片懒加载 Hooks 的步骤

在这里我们提供啦两个方式一种是原生封装Hooks函数,另一种是使用vue3-lazyload库来实现图片懒加

首先我们需要在src下创建一个hooks文件夹,在文件夹下新建一个useLazyLoad.js

  1. 原生Hooks封装

    1. import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
      export default function useLazyLoad() {
        // 用于存储图片是否加载完成的响应式状态
        const isLoaded = ref(false);
      
        // 加载图片的函数
        const loadImage = (imgElement) => {
            if (!imgElement) return;
      
            const observer = new IntersectionObserver((entries) => {
                entries.forEach((entry) => {
                    if (entry.isIntersecting) {
                        const img = entry.target;
                        img.src = img.dataset.src;
                        isLoaded.value = true;
                        observer.disconnect();
                    }
                });
            });
      
            observer.observe(imgElement);
        };
      
        // 在组件挂载时执行的逻辑
        onMounted(() => {
            // 使用nextTick确保DOM更新完成后再获取图片元素
            nextTick(() => {
                const imgElements = document.querySelectorAll('img[data-src]');
                imgElements.forEach((img) => {
                    loadImage(img);
                });
            });
        });
      
        // 在组件卸载前执行的逻辑
        onBeforeUnmount(() => {
            const observers = [];
            const imgElements = document.querySelectorAll('img[data-src]');
            imgElements.forEach((img) => {
                const observer = img.__observer;
                if (observer) {
                    observers.push(observer);
                }
            });
      
            observers.forEach((observer) => {
                observer.disconnect();
            });
        });
      
        return {
            isLoaded
        };
      }
      

      代码解释:
      1. isLoaded是一个响应式引用,用于跟踪图片是否已经加载完成。
      2. loadImage函数创建了一个IntersectionObserver实例来观察图片是否进入浏览器的可视区域。当图片进入可视区域时,将图片的src属性设置为预先存储在data-src属性中的真实图片地址,同时将isLoaded设置为true,并断开观察器。
      3. onMounted钩子函数在组件挂载时被调用。这里先使用nextTick确保 DOM 更新完成后,获取所有带有data-src属性的图片元素,并对每个元素调用loadImage函数来开始监听它们的加载时机。
      4. onBeforeUnmount钩子函数在组件卸载前被调用。它获取所有带有data-src属性的图片元素对应的观察器,并断开它们,以避免内存泄漏。
    2. Vue3-lazyload库封装

                        1.首先,需要安装vue3-lazyload这个库来辅助实现图片懒加载功能。可以通过以下命令进行安装: 

npm install vue3-lazyload

                        2.

import { ref, onMounted, onBeforeUnmount } from 'vue';
import lazyLoad from 'vue3-lazyload';
export default function useLazyLoad() {
    // 创建一个响应式的对象来存储图片加载状态
    const isLoaded = ref(false);

    // 定义加载图片的函数
    const loadImage = (imgElement) => {
        if (!imgElement) return;

        const observer = new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                if (entry.isIntersecting) {
                    lazyLoad(entry.target);
                    isLoaded.value = true;
                    observer.disconnect();
                }
            });
        });

        observer.observe(imgElement);
    };

    // 在组件挂载时,绑定加载图片的事件
    onMounted(() => {
        const imgElements = document.querySelectorAll('img[data-src]');
        imgElements.forEach((img) => {
            loadImage(img);
        });
    });

    // 在组件卸载前,清除所有的观察器
    onBeforeUnmount(() => {
        const observers = [];
        const imgElements = document.querySelectorAll('img[data-src]');
        imgElements.forEach((img) => {
            const observer = img.__observer;
            if (observer) {
                observers.push(observer);
            }
        });

        observers.forEach((observer) => {
            observer.disconnect();
        });
    });

    return {
        isLoaded
    };
}

 

1.首先创建了一个isLoaded的响应式引用,用于跟踪图片是否已经加载完成。

2.loadImage函数用于创建一个IntersectionObserver来观察图片是否进入到浏览器的可视区域。当图片进入可视区域时,就使用vue3-lazyload库来加载图片,并将isLoaded设置为true,然后断开观察器。

3.在onMounted钩子函数中,获取所有带有data-src属性的图片元素,并对每个元素调用loadImage函数来开始监听它们的加载时机。

4.在onBeforeUnmount钩子函数中,获取所有带有data-src属性的图片元素对应的观察器,并断开它们,以避免内存泄漏。

四、性能优化考虑

在实现图片懒加载过程中可以进行的一些性能优化措施。比如合理设置IntersectionObserver的阈值,避免过于频繁地检查图片是否进入可视区;对图片进行适当的压缩处理,减少图片加载的数据量等。

通过性能监测工具(如 Chrome 开发者工具中的性能面板)来评估懒加载的效果以及进一步优化的方向。

<think>好的,我现在需要帮助用户了解如何在Vue3封装Hooks。首先,我需要回顾一下Vue3的Composition API,因为Hooks在这里是通过组合式函数实现的。用户可能已经知道Hooks的基本概念,但需要具体的步骤和示例。 根据提供的引用内容,Vue3Hooks结合了响应式系统,用于逻辑复用,类似于React Hooks但有所不同。用户可能需要一个清晰的示例教程,比如封装一个useTable的Hooks,如引用[2]提到的。我应该分步骤讲解,从创建Hooks文件到定义响应式数据,再到添加方法,最后在组件中使用。 我需要确保每一步都解释清楚,比如使用ref和reactive创建响应式状态,如何导出函数,以及组件中如何导入和使用。同时,要强调封装的好处,比如复用性、可维护性,以及和Mixin的对比,如引用[3]提到的。 可能还需要考虑如何处理异步请求,比如在useTable中获取数据,这时可以使用async/await。此外,要提到最佳实践,比如单一职责和自定义配置,让Hooks更灵活。最后,生成相关问题,帮助用户进一步学习,比如封装Hooks的注意事项或者与React Hooks的区别。 需要检查是否遵循了用户提供的格式要求,比如行内数学表达式是否正确,但这里可能用不上数学公式。重点是将步骤用代码块展示,语言标记正确,结构清晰。确保引用标识正确添加,比如在提到复用性时引用[3],提到useTable时引用[2]。 现在组织内容:简介、封装步骤(分点)、示例代码、最佳实践、相关问题。确保每个部分自然衔接,引用放置在相关段落末尾。可能需要先定义什么是Hooks,再逐步展开,避免术语混淆。最后验证示例代码是否正确,比如useTable的函数结构,是否正确使用reactive和生命周期钩子。</think>### Vue3 Hooks 封装示例教程 #### 一、Hooks 封装核心思想 Vue3 Hooks(组合式函数)是通过组合式API封装响应式逻辑的代码复用方案。其核心是将组件中的状态和逻辑抽离为独立函数,通过响应式系统实现高效复用[^3]。 --- #### 二、封装步骤与示例(以 `useTable` 为例) ##### 1. 创建 Hooks 文件 ```javascript // useTable.js import { ref, reactive, onMounted } from &#39;vue&#39; import { fetchTableData } from &#39;@/api&#39; // 假设存在数据接口 export default function useTable(options = {}) { // 定义响应式状态 const state = reactive({ loading: false, data: [], pagination: { current: 1, pageSize: 10, total: 0 } }) // 定义业务方法 const loadData = async () => { state.loading = true try { const params = { page: state.pagination.current, pageSize: state.pagination.pageSize } const res = await fetchTableData(params) state.data = res.data state.pagination.total = res.total } finally { state.loading = false } } // 生命周期挂钩 onMounted(() => { loadData() }) // 返回可复用状态与方法 return { state, loadData } } ``` ##### 2. 在组件中使用 ```vue <template> <div> <table v-loading="state.loading"> <!-- 表格内容渲染 --> </table> <Pagination :current="state.pagination.current" :total="state.pagination.total" @change="handlePageChange" /> </div> </template> <script setup> import useTable from &#39;./useTable&#39; const { state, loadData } = useTable() const handlePageChange = (page) => { state.pagination.current = page loadData() } </script> ``` --- #### 三、封装最佳实践 1. **单一职责原则** 每个Hooks应只解决一个特定问题,例如 `useForm` 处理表单逻辑,`useFetch` 管理数据请求[^1]。 2. **响应式状态管理** 优先使用 `reactive` 管理关联状态对象,用 `ref` 处理独立值: $$ \text{响应式变量} = \begin{cases} \text{reactive()} & \text{复杂对象} \\ \text{ref()} & \text{基础类型} \end{cases} $$ 3. **支持自定义配置** 通过参数注入提升灵活性: ```javascript function useTable({ immediate = true }) { // 立即加载数据配置 } ``` --- #### 四、对比传统方案优势 | 方案 | 代码组织 | 类型推导 | 作用域隔离 | |-----------|------|------|-------| | Mixins | 差 | 困难 | 弱 | | Hooks | 清晰 | 友好 | 强 | [^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值