图片懒加载(自定义指令)

news2024/10/30 16:40:18

-----------------------------------------------------------

  • 图片懒加载
    • 自定义指令
    • 使用mock模拟随机图片
    • 列表组件如下(主要内容):
    • 配置自定义指令

图片懒加载

实现思路

使用自定义指令实现通用图片懒加载(在图片到达视口内时再进行加载)

自定义指令

可以理解为另一个生命周期,在各个钩子函数中处理相关内容,常用的钩子函数如下

// 自定义指令配置
export default {
	// 只调用一次,指令第一次绑定到元素时调用
	bind(el,boundings){
		// 处理
	},
    // 被绑定元素插入父节点时调用 
    inserted(el,boundings){
        // 处理
    },
    // 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前
    update(el,boundings){
    	// 处理
    }
    // 只调用一次,指令与元素解绑时调用
    unbind(el){
        // 处理
    }
}

通常是使用对象来配置,当bind钩子与update钩子内容一致,而不关心其它的钩子时可以简写为函数配置:

// 自定义指令配置
export default function(el,boundings){
	// 处理
}

使用mock模拟随机图片

Mock.mock(/^\/api\/blog(\?.+)?$/,"get",function(options){
    // 使用动态模拟数据
    const query = qs.parse(options.url);
    return Mock.mock({
        "code": 0,
        "msg": "string",
        "data": {
            "total|200-800": 0,
            [`rows|${query.limit||10}`]: [
            {
                "id": "@guid",
                "title": "@ctitle",
                "description": "@cparagraph(1,10)",
                "createDate": "@date('T')",
                "scanNumber|1000-10000": 0,
                "commentNumber|0-400": 0,
                "category": {
                    "id|0-10": 0,
                    "name": "分类@id"
                },
                "thumb|1": ["@image(300x250,@color,#fff,@natural)",null]
            }
            ]
        }
    })
})

列表组件如下(主要内容):

<template>
  <div class="bloglist-container" v-loading="isLoading" ref="bloglistRef">
    <ul class="list">
        <li class="item" v-for="item in data.rows" :key="item.id">
            <router-link :to="{
                name: '/blogDetail',
                params: {
                    id: item.id
                }
            }">
                <div class="img"  v-if="item.thumb">
                    <!-- 绑定自定义指令 -->
                    <img :src="item.thumb" class="image" v-lazy="item.thumb">
                </div>
            </router-link>
            <div :class="item.thumb?'txt':'ptxt'">
                <router-link :to="{
                    name: '/blogDetail',
                    params: {
                        id: item.id
                    }
                }">
                    <h2 class="title">{{ item.title }}</h2>
                </router-link>
                <div class="info">
                    <span>日期:{{ formatDate(item.createDate) }}</span>
                    <span>浏览:{{ item.scanNumber }}</span>
                    <span>评论:{{ item.commentNumber }}</span>
                    <router-link :to="{
                        name:'/categoryBlog',
                        params: {categoryId: item.category.id}
                    }">
                        <span class="cate">分类:{{ item.category.id }}</span>
                    </router-link>
                </div>
                <p class="desc">{{ item.description }}</p>
            </div>
        </li>
    </ul>
    <Pager :current="this.page" :total="data.total" :limit="this.limit" 
    @pageChange="handlePageChange"/>
  </div>
</template>

<script>
import * as blogApi from '@/api/blog.js'
import fetchData from '@/mixins/fetchData';
import { formatDate } from '@/utils/formatDate';
import Pager from '@/components/Pager';
import scrollEvent from '@/mixins/scrollEvent';
export default {
    mixins: [fetchData({}),scrollEvent("bloglistRef")],
    components: {
        Pager,
        BackTop
    },
    computed:{
        page(){
            return +this.$route.query.page || 1;
        },
        limit(){
            return +this.$route.query.limit || 10;
        },
        categoryId(){
            return +this.$route.params.categoryId || -1;
        }
    },
    methods:{
        // 获取文章列表
        async getFetchData(){
            return await blogApi.getBlog(this.page,this.limit,'',this.categoryId);
            
        },
        formatDate,
    },
}
</script>

在这里插入图片描述

配置自定义指令

使用一个数组保存ajax获取的所有列表元素相关内容,然后在元素插入父组件时先进行一次处理,将初始就在视口的图片加载,已经加载完毕的元素相关内容会被数组删除,然后通过滚动事件来进行图片处理,最后进行事件清除,具体如下:

import defaultImg from '@/assets/default.gif';
import eventBus from '@/eventBus';
import {deBounce} from '@/utils'

// 刚开始ajax获取的所有图片相关节点、src都在内,处理后会被此数组剔除
let imgs = [];      // 需要处理的图片数组

/**
 * 处理图片,先赋值默认图片,如在视口内则加载源图片
 * @param {*} i 数组内容,包含该元素dom,以及图片源src
 */
function setImage(i){
    // 先使用默认图片
    i.dom.src = defaultImg;
    // 判断是否位于视口内
    const clientHeight = document.documentElement.clientHeight;
    const domTop = i.dom.getBoundingClientRect().top;
    const domHeight = i.dom.getBoundingClientRect().height || 250;
    // console.log(clientHeight,domTop,domHeight);
    if(domTop >= -domHeight && domTop <= clientHeight){
        // 在视口内
        i.dom.src = i.src;
        // 处理完成后清除数组中相关内容
        imgs.filter((img)=> img!==i);
    }
    
}
/**
 * 批量处理所有图片
 */
function setImages(){
    for (const i of imgs) {
        setImage(i);
    }
}
/**
 * 用于触发setImages
 */
function handleScroll() {
    setImages();
  }

// 事件总线监听滚动
eventBus.$on('blogMainScroll',deBounce(handleScroll,50));

// 自定义指令配置
export default {
    // 被绑定元素插入父节点时调用 
    inserted(el,boundings){
        const img = {
            dom: el,
            src: boundings.value
        };
        imgs.push(img);
        setImage(img)  // 处理最开始的数组内容
    },
    // 只调用一次,指令与元素解绑时调用
    unbind(el){
        // 处理结束后,清除数组内相关内容,避免重复处理
        imgs = imgs.filter((img) => img.dom !== el);
    }
}

在这里插入图片描述

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

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

相关文章

socket编程---UDP

目录 一、socket 二、socket接口 1.流程原理 2.代码 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; socket编程又称套接字编程&#xff0c;指进行网络通信程序的编写 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、soc…

R语言机器学习算法实战系列(十四): CatBoost分类算法+SHAP值 (categorical data gradient boosting)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍CatBoost的原理CatBoost的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割设置数据对象调节参数训练模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC Curv…

创建ODBC数据源SQLConfigDataSource函数的用法

网络上没有这个函数能实际落地的用法说明&#xff0c;我实践后整理一下&#xff1a; 1.头文件与额外依赖库&#xff1a; #include <odbcinst.h> #pragma comment(lib, "legacy_stdio_definitions.lib") 2.调用函数&#xff1a; if (!SQLConfigDataSourceW(…

HCIP-HarmonyOS Application Developer V1.0 笔记(一)

HarmonyOS的系统特性 硬件互助&#xff0c;资源共享;一次开发&#xff0c;多端部署;统一OS&#xff0c;弹性部署。 分布式软总线&#xff1a;分布式任务调度、分布式数据管理、分布式硬件虚拟化的基座 18N的独立设备 1个手机&#xff0c;8种设备&#xff08;车机&#xff0c…

upload-labs靶场Pass-21

upload-labs靶场Pass-21 本关上传方法众多&#xff0c;但是应该考察的是数组后缀绕过&#xff0c;所以我的上传围绕此展开 1.分析源码 $is_upload false; // 初始化上传状态为false $msg null; // 初始化消息变量为null// 检查是否有文件上传 if(!empty($_FILES[upload_fi…

【undefined reference to xxx】zookeeper库编译和安装 / sylar项目ubuntu20系统编译

最近学习sylar项目&#xff0c;编译项目时遇到链接库不匹配的问题&#xff0c;记录下自己解决问题过程&#xff0c;虽然过程很艰难&#xff0c;但还是解决了&#xff0c;以下内容供大家参考&#xff01; undefined reference to 问题分析 项目编译报错 /usr/bin/ld: ../lib/lib…

网络服务ssh

Linux 网络基础 一、知识回顾 网络地址&#xff1a;互联网协议地址&#xff08;IP地址&#xff09;为互联网上每一个网络或主机分配一个逻辑地址&#xff0c;IP地址工作在网络层。 ​ IP的分类&#xff1a;IPV4 IPV6 物理地址&#xff1a;物理地址&#xff08;MAC地址&…

Git获取本地仓库和常用指令

一、获取本地仓库 1&#xff09;在电脑的任意位置创建一个空目录&#xff08;例如test01&#xff09;作为我们的本地Git仓库 2&#xff09;进入这个目录中&#xff0c;点击右键打开Git bash窗口 3&#xff09;执行命令git init&#xff08;初始化当前目录为一个git仓库&…

解决报错:JDK版本不正确

加载maven过程中&#xff0c;控制台报错&#xff1a; Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.…

Webserver(1.8)操作函数

目录 文件属性操作函数access函数chmod函数chown函数truncate函数 目录操作函数mkdir函数rmdir函数rename函数chdir函数*getcwd函数 目录遍历函数*opendir函数*readdir函数closedir函数 dup、dup2函数dupdup2 fcntl函数 文件属性操作函数 access函数 判断某个文件是否有某个权…

解决ElasticSearch启动成功却无法在浏览器访问问题

目录 前言&#xff1a; 问题复现 &#xff1a; 解决问题&#xff1a; 1、修改sysctl.conf文件 2、在sysctl.conf文件增加这段东西 3、 然后保存退出&#xff0c;输入以下命令使其生效 结语&#xff1a; 前言&#xff1a; 这篇文章是小白我今天突然启动es&#xff0c;发现e…

【tomcat系列漏洞利用】

Tomcat 服务器是一个开源的轻量级Web应用服务器&#xff0c;在中小型系统和并发量小的场合下被普遍使用。主要组件&#xff1a;服务器Server&#xff0c;服务Service&#xff0c;连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。一个Container…

如何在Linux系统中使用SSH Key认证进行无密码登录

如何在Linux系统中使用SSH Key认证进行无密码登录 SSH Key认证简介 安装SSH 在Debian/Ubuntu系统中检查 在CentOS/RHEL系统中检查 生成SSH密钥 复制公钥到远程服务器 配置SSH服务端 编辑SSH配置文件 重启SSH服务 测试无密码登录 SSH Key认证的高级配置 设置密钥的权限 限制密…

开发流程初学者指南——需求分析

目录 从零开始理解需求分析什么是需求分析&#xff1f;需求分析的目标需求分析的基本原则需求分析的各个阶段需求分析的常用方法和工具编写需求文档总结 从零开始理解需求分析 需求分析是软件开发过程中不可或缺的一环&#xff0c;它帮助我们明确用户的需求&#xff0c;确保最…

MySQL Workbench工作台汉化

一、下载汉化包 通过百度网盘分享的文件&#xff1a;MySQL汉化包.rar 链接&#xff1a;https://pan.baidu.com/s/1PaJSU9dvVnQQWEESHSue5Q 二、汉化过程 注意&#xff1a;替换之前一定要记得把两个文件复制出来存着&#xff0c;防止替换失败修改了文件 找到MySQL的工作台da…

AI数字人应用场景超全解析(下)

​​一、AI数字人技术发展趋势 1、技术迭代与创新 AI数字人技术的迅猛进步&#xff0c;得益于人工智能、计算机图形学、动作捕捉及3D建模等领域的突破性进展。深度学习算法的优化&#xff0c;让AI数字人的语言理解和生成能力愈发自然&#xff0c;能够提供更加精准和个性化的交…

实战-任意文件下载

实战-任意文件下载 1、开局 开局一个弱口令&#xff0c;正常来讲我们一般是弱口令或者sql&#xff0c;或者未授权 那么这次运气比较好&#xff0c;直接弱口令进去了 直接访问看看有没有功能点&#xff0c;正常做测试我们一定要先找功能点 发现一个文件上传点&#xff0c;不…

激光自动对焦显微系统的原理和作用

原理 激光自动对焦原理&#xff1a; &#xff08;1&#xff09;激光自动对焦显微系统利用激光束的自聚焦特性实现精确焦点控制。在检测过程中&#xff0c;激光束通过照明针孔形成点光源&#xff0c;对样品表面进行扫描。 &#xff08;2&#xff09;被照射的点在探测针孔处成像…

【数据集】全球30弧秒网格人为热通量数据(AHF)

【数据集】全球30弧秒网格人为热通量数据(AHF) 数据概述数据下载数据处理基于Python绘制研究区内人为热通量数据(AHF)基于Python插值获取2020年人为热通量数据参考人为热通量(anthropogenic heat flux)数据是指由人类活动引起的地表热量变化的定量数据。这些数据通常用于…

电子邮件防泄密系统怎么选?分享五款邮件加密工具,好不好用你说的算!(宝藏篇)

电子邮件防泄密系统怎么选&#xff1f; 根据国际IT安全公司的研究&#xff0c;有70%的企业在担心电子邮件可能泄密&#xff0c;约一半员工承认曾错误发送不当或机密邮件。 尽管许多企业已经意识到了"邮件危机"&#xff0c;但仍未找到有效解决方案。 邮件发送不受控…