uniapp 小程序图片懒加载组件 ImageLazyLoad

预览图

请添加图片描述

组件【ImageLazyLoad】代码

<template><viewclass="image-lazy-load":style="{opacity: opacity,borderRadius: borderRadius + 'rpx',background: background,transition: `opacity ${time / 1000}s ease-in-out`,}":class="'image-lazy-load-item-' + elIndex"><view :class="'image-lazy-load-item-' + elIndex" style="height: 100%"><image:style="{ borderRadius: borderRadius + 'rpx', height: imgHeight, width: imgWidth }"v-if="!isError"class="image-lazy-load-item":src="isShow ? imageUrl : loadingImg":mode="imgMode"@load="imgLoaded"@error="loadError"@tap="clickImg"></image><!-- 1. 空白占位符-因为自己的项目不需要失败时的图片占位,所以这里就用一个div来占位2. 如果需要用图片来占位,请注释掉这里代码,把下面那段代码注释去掉就行--><viewv-elseclass="image-lazy-load-item":style="{ borderRadius: borderRadius + 'rpx', height: imgHeight, width: imgWidth, background: background }"></view><!-- <image:style="{ borderRadius: borderRadius + 'rpx', height: imgHeight, width: imgWidth }"class="image-lazy-load-item error"v-else:src="showErrorImg ? errorImg : ''":mode="imgMode"@load="errorImgLoaded"@tap="clickImg"></image> --></view></view>
</template><script>
/*** ImageLazyLoad 图片懒加载组件* @description 懒加载使用的场景为:页面有很多图片时,首次加载很慢,导致用户体验感不好.* @property {String Number} index 用户自定义值,在事件触发时回调,用以区分是哪个图片,一般用于图片预览* @property {String} image 图片路径* @property {String} loadingImg 预加载时的占位图* @property {String} errorImg 图片加载出错时的占位图* @property {String} threshold 触发加载时的位置,见上方说明,单位 rpx(默认300)* @property {String Number} duration 图片加载成功时,淡入淡出时间,单位ms(默认)* @property {String} effect 图片加载成功时,淡入淡出的css动画效果(默认ease-in-out)* @property {Boolean} isEffect 图片加载成功时,是否启用淡入淡出效果(默认true)* @property {String Number} borderRadius 图片圆角值,单位rpx(默认0)* @property {String Number} width 图片宽度,(默认100%,传值带上单位)* @property {String Number} height 图片高度,注意:实际高度可能受imgMode参数影响(默认450rpx 传值带上单位)* @property {String Number} imgMode 图片的裁剪模式,详见image组件裁剪模式(默认aspectFill)* @property {String} background 占位图片背景色* @property {Boolean} showErrorImg 显示加载失败图片(默认false)* @event {Function} click 点击图片时触发* @event {Function} load 图片加载成功时触发* @event {Function} error 图片加载失败时触发* @example <ImageLazyLoad :image="image"></ImageLazyLoad>*/
export default {name: "ImageLazyLoad",props: {index: {type: [Number, String],},// 要显示的图片image: {type: String,default: "",},// 图片裁剪模式imgMode: {type: String,default: "aspectFill",},// 占位图片路径loadingImg: {type: String,default: "",},// 加载失败的错误占位图errorImg: {type: String,default: "",},// 图片进入可见区域前多少像素时,单位rpx,开始加载图片// 负数为图片超出屏幕底部多少距离后触发懒加载,正数为图片顶部距离屏幕底部多少距离时触发(图片还没出现在屏幕上)threshold: {type: [Number, String],default: 300,},// 淡入淡出动画的过渡时间duration: {type: [Number, String],default: 300,},// 渡效果的速度曲线,各个之间差别不大,因为这是淡入淡出,且时间很短,不是那些变形或者移动的情况,会明显// linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n);effect: {type: String,default: "ease-in-out",},// 是否使用过渡效果isEffect: {type: Boolean,default: true,},// 圆角值borderRadius: {type: [Number, String],default: 0,},// 图片宽度,单位rpxwidth: {type: [Number, String],default: "100%",},// 图片高度,单位rpxheight: {type: [Number, String],default: "450rpx",},// 占位背景色background: {type: String,default: "",},// 显示错误图片showErrorImg: {type: Boolean,default: false,},},data() {return {imageUrl: this.image, // 正在要显示的图片路径isShow: false,opacity: 1,time: this.duration,loadStatus: "", // 默认是懒加载中的状态isError: false, // 图片加载失败elIndex: this.generateRandomString(32),isConnected: true, // 网络是否连接 默认连接};},computed: {// 将threshold从rpx转为pxgetThreshold() {// 先取绝对值,因为threshold可能是负数,最后根据this.threshold是正数或者负数,重新还原let thresholdPx = uni.upx2px(Math.abs(this.threshold));return this.threshold < 0 ? -thresholdPx : thresholdPx;},// 计算图片的高度,可能为auto,带%,或者直接数值imgHeight() {return this.height;},imgWidth() {return this.width;},},created() {// 由于一些特殊原因,不能将此变量放到data中定义this.observer = {};},watch: {isShow(nVal) {// 如果是不开启过渡效果,直接返回if (!this.isEffect) return;this.time = 0;// 原来opacity为1(不透明,是为了显示占位图),改成0(透明,意味着该元素显示的是背景颜色,默认的白色),再改成1,是为了获得过渡效果this.opacity = 0;// 延时30ms,否则在浏览器H5,过渡效果无效setTimeout(() => {this.time = this.duration;this.opacity = 1;}, 30);},// 图片路径发生变化时,需要重新标记一些变量,否则会一直卡在某一个状态,比如isErrorimage(n) {if (!n) {// 如果传入null或者'',或者undefined,标记为错误状态this.isError = true;} else {this.init();this.isError = false;}},// 监听网络变化, 防止网络断开重连的时候,图片一直加载不出来bugisConnected(newVal) {if (newVal) {this.init();this.isError = false;// 图片链接加个时间戳,防止加载失败后出现缓存,// 导致联网后,刷新页面加载失败的图片不能重新加载,而出现空白的bugthis.imageUrl = this.image + '?time=' + Date.now()}},},emits: ["click", "load"],methods: {// 用于重新初始化init() {this.isError = false;this.loadStatus = "";},// 点击图片触发的事件,loadlazy-还是懒加载中状态,loading-图片正在加载,loaded-图片加加载完成clickImg() {let whichImg = "";// 如果isShow为false,意味着图片还没开始加载,点击的只能是最开始的占位图if (this.isShow == false) whichImg = "lazyImg";// 如果isError为true,意味着图片加载失败,这是只剩下错误的占位图,所以点击的只能是错误占位图// 当然,也可以给错误的占位图元素绑定点击事件,看你喜欢~else if (this.isError == true) whichImg = "errorImg";// 总共三张图片,除了两个占位图,剩下的只能是正常的那张图片了else whichImg = "realImg";// 只通知当前图片的indexthis.$emit("click", this.index);},// 图片加载完成事件,可能是加载占位图时触发,也可能是加载真正的图片完成时触发,通过isShow区分imgLoaded() {// 占位图加载完成if (this.loadStatus == "") {this.loadStatus = "lazyed";}// 真正的图片加载完成else if (this.loadStatus == "lazyed") {this.loadStatus = "loaded";this.$emit("load", this.index);}},// 错误的图片加载完成errorImgLoaded() {this.$emit("error", this.index);},// 图片加载失败loadError() {this.isError = true;},disconnectObserver(observerName) {const observer = this[observerName];observer && observer.disconnect();},// 生成一个32位由字母组成的字符串generateRandomString(length) {let result = "";const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";for (let i = 0; i < length; i++) {result += characters.charAt(Math.floor(Math.random() * characters.length));}return result;},},beforeUnmount() {// 销毁页面时,可能还没触发某张很底部的懒加载图片,所以把这个事件给去掉//observer.disconnect();},mounted() {// 监听网络变化, 防止网络断开重连的时候,图片一直加载不出来buguni.onNetworkStatusChange((res) => {// console.log("网络变化:", res.isConnected);this.isConnected = res.isConnected;});// mounted的时候,不一定挂载了这个元素,延时30ms,否则会报错或者不报错,但是也没有效果setTimeout(() => {// 这里是组件内获取布局状态,不能用uni.createIntersectionObserver,而必须用this.createIntersectionObserver// this.disconnectObserver('contentObserver');const contentObserver = uni.createIntersectionObserver(this);// 要理解这里怎么计算的,请看这个:// https://blog.csdn.net/qq_25324335/article/details/83687695contentObserver.relativeToViewport({bottom: this.getThreshold,}).observe(".image-lazy-load-item-" + this.elIndex, (res) => {// console.log("relativeToViewport", res);if (res.intersectionRatio > 0) {// 懒加载状态改变this.isShow = true;// 如果图片已经加载,去掉监听,减少性能的消耗this.disconnectObserver("contentObserver");}});this.contentObserver = contentObserver;}, 30);},
};
</script><style scoped lang="scss">
.image-lazy-load {background-color: #fff;overflow: hidden;&-item {width: 100%;transform: transition3d(0, 0, 0);// 防止图片加载“闪一下”will-change: transform;/* #ifndef APP-NVUE */display: block;/* #endif */}
}
</style>

组件使用【组件引入这里就不介绍】

 <ImageLazyLoadwidth="100%"height="calc((100vw - 24px - 8px) / 2)":image="item.url"threshold="300"></ImageLazyLoad>

说明:根据自己情况,设置对应的宽高就行

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

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

相关文章

第二代增强-采购订单抬头子屏幕增强

文章目录 第二代增强-采购订单抬头子屏幕增强需求查找增强点创建项目增强子屏幕定义全局变量编写出口函数代码激活增强运行结果查看创建的采购订单底表数据 第二代增强-采购订单抬头子屏幕增强 需求 查找增强点 创建项目 增强子屏幕 定义全局变量 *&---------------------…

读书笔记——《高质量C++/C编程指南》(2)

目录 前言 命名规则 共性规则 简单的Windows应用程序命名规则 表达式和基本语句 运算符优先级 复合表达式 if语句 布尔变量与零值比较 整型变量与零值比较 浮点变量与零值比较 指针变量与零值比较 对if 语句的补充说明 循环语句的效率 for 语句的循环控制变量 s…

自动驾驶中常见坐标系极其转换

各个传感器坐标系 相机坐标系统 摄像头的作用是把三维世界中的形状、颜色信息,压缩到一张二维图像上。基于摄像头的感知算法则是从二维图像中提取并还原三维世界中的元素和信息,如车道线,车辆、行人等,并计算他们与自己的相对位置。 感知算法和相机相关的坐标系有图像坐…

Pandas进阶

文章目录 第1关&#xff1a;Pandas 分组聚合第2关&#xff1a;Pandas 创建透视表和交叉表 第1关&#xff1a;Pandas 分组聚合 编程要求 使用 Pandas 中的 read_csv() 函数读取 step1/drinks.csv 中的数据&#xff0c;数据的列名如下表所示&#xff0c;请根据 continent 分组并…

MySQL-ELK基础

1&#xff1a;什么是 ELK ELK是由一家elastic公司开发的三个开源项目的首字母缩写&#xff0c;这三个项目分别是&#xff1a;Elasticsearch、Logstash 和 Kibana。三个项目各有不同的功能&#xff0c;之后又增加了许多新项目, 于是 从5.X版本后改名为Elastic Stack Elastic S…

【JavaScript】内置对象 - Date 日期对象 ④ ( 制作倒计时页面 )

文章目录 一、倒计时页面实现1、需求分析2、计算秒数3、计算倒计时时间的 天 / 时 / 分 / 秒4、页面中显示倒计时时间 二、完整代码示例1、完整代码2、执行结果 Date 日期对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Da…

速卖通商品评论API(aliexpress.item_review)返回值全解析

在电商领域&#xff0c;用户评论对于产品的推广和销售具有极其重要的影响。速卖通&#xff08;AliExpress&#xff09;作为全球知名的跨境电商平台&#xff0c;提供了丰富的API接口供开发者使用&#xff0c;其中aliexpress.item_review API允许开发者获取商品的评论信息。本文将…

品质为王:高效溶解性鱼油胶囊的软胶囊弹性硬度测试解析

品质为王&#xff1a;高效溶解性鱼油胶囊的软胶囊弹性硬度测试解析 在当今的健康产品市场中&#xff0c;高效溶解性鱼油胶囊以其独特的营养价值和吸收效率赢得了众多消费者的青睐。然而&#xff0c;要想在激烈的市场竞争中脱颖而出&#xff0c;产品的品质保证至关重要。其中&a…

深入理解WPF的ResourceDictionary

深入理解WPF的ResourceDictionary 介绍 在WPF中&#xff0c;ResourceDictionary用于集中管理和共享资源&#xff08;如样式、模板、颜色等&#xff09;&#xff0c;从而实现资源的重用和统一管理。本文详细介绍了ResourceDictionary的定义、使用和合并方法。 定义和用法 Res…

鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行

本篇有相当的难度&#xff0c;涉及用户栈和内核栈的两轮切换&#xff0c;CPU四次换栈&#xff0c;寄存器改值&#xff0c;将围绕下图来说明. 解读 为本篇理解方便&#xff0c;把图做简化标签说明: user:用户空间kernel:内核空间source(…):源函数sighandle(…):信号处理函数&a…

【操作系统】进程与线程概念基础知识

进程与线程概念基础知识 进程进程的概念进程控制块进程状态进程三状态模型挂起进程模模型进程的上下文切换进程控制 线程为什么引入线程线程的概念线程与进程的比较线程的上下文切换线程的实现 进程 进程的概念 1. 进程的定义&#xff1a; 进程是指一个具有一定独立功能的程序…

【面试干货】http请求报文的组成与作用?

【面试干货】http请求报文的组成与作用&#xff1f; 一、http 的请求报文组成二、请求行&#xff08;Request Line&#xff09;三、请求头部&#xff08;Request Headers&#xff09;四、请求体&#xff08;Request Body&#xff09;五、响应头部 &#xff08;Response Headers…

iframe的基本用法

一、背景 在web页面开发中,有时会遇到在一个应用A的页面中引用应用B的页面,此时就需要在应用A中使用iframe嵌入引用B的页面了,比如多租户的web应用,或者门户系统的智能客服助手弹框应用,博主也是在做通用智能客服应用的过程中用到了iframe。网络上有关iframe的信息虽然很…

银河麒麟桌面版开机后网络无法自动链接 麒麟系统开机没有连接ens33

1.每次虚拟机开机启动麒麟操作系统&#xff0c;都要输入账号&#xff0c;密码。 进入点击这个ens33 内网才连接 2. 如何开机就脸上呢&#xff1f; 2.1. 进入 cd /etc/sysconfig/network-scripts 2.2 修改参数 onbootyes 改为yes 2.3 重启即可 a. 直接重启机器查看是否正常&…

工程伦理课堂记录

文章目录 0. 导论0.1 工程伦理教育的意义0.2 工程伦理教育要实现的目标 1. 工程与伦理1.1 工程伦理学科的产生1.2 工程和技术1.3 工程概念的理解演进1.4 工程的过程1.5 工程的特点1.6 工程活动的七个维度总结 2. 伦理2.1 道德伦理的概念2.2 道德伦理的关系2.3 伦理规范2.4 伦理…

【吃透Java手写】2-Spring(下)-AOP-事务及传播原理

【吃透Java手写】Spring&#xff08;下&#xff09;AOP-事务及传播原理 6 AOP模拟实现6.1 AOP工作流程6.2 定义dao接口与实现类6.3 初始化后逻辑6.4 原生Spring的方法6.4.1 实现类6.4.2 定义通知类&#xff0c;定义切入点表达式、配置切面6.4.3 在配置类中进行Spring注解包扫描…

Blender动画与云渲染:创造高质量作品的未来路径

Blender作为开源的3D图形软件&#xff0c;在多个领域广受欢迎。但随着项目复杂度提升&#xff0c;传统渲染方式受限。云渲染技术的兴起突破了这些限制&#xff0c;为创作者提供了更自由、高效的创作环境。 一、Blender动画项目的挑战 传统上&#xff0c;Blender动画渲染需要依…

代码审计-php篇之某CRM系统多处sql注入

&#x1f31f; ❤️ 作者&#xff1a;yueji0j1anke 首发于公号&#xff1a;剑客古月的安全屋 字数&#xff1a;3516 阅读时间: 35min 声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果…

实战 | 实时手部关键点检测跟踪(附完整源码+代码详解)

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

苹果平板HOME键成历史,全面屏时代到来?2024平板电脑市场趋势分析

近期苹果公司在“放飞吧”发布会上推出了新款iPad Pro和iPad Air平板电脑&#xff0c;并下架了最后一款带有实体Home按键的iPad 9。这一变化标志着Home键在苹果iPad产品线中成为了历史&#xff0c;引起了不少网友的怀念和感慨。 与此同时&#xff0c;今年3月线上平板电脑市场迎…