【uniapp 图片懒加载】附源代码

提示:前端查漏补缺,仅代表个人观点

文章目录


提示:以下是本篇文章正文内容,下面案例可供参考

一、实现原理

使用 intersectionObserver API 监听节点的相交情况实现懒加载

二、源代码

<template>
    	<view class="muqian-content" :style="{
    			width,
    			height,
    		}">
    		<!-- 加载中 -->
    		<image :src="loadSrc" class="muqian-image muqain-load" @load="init"  mode="aspectFill" :style="{
    				opacity:isShow?'0':'1',
    				borderRadius,
    				width,
    				height,
    				transition: `opacity ${duration/1000}s ${effect}`
    				}"></image>
    				
    		<!-- 加载成功 -->
    		<image class="muqian-image" @load="load" @error="error" v-if="status==1" :src="src" mode="aspectFill" :style="{
    				opacity:isShow?'1':'0',
    				borderRadius,
    				width,
    				height,
    				transition: `opacity ${duration/1000}s ${effect}`
    				}">
    		</image>
    		<!-- 加载失败 -->
    		<image class="muqian-image" v-if="status==2" :src="errorSrc" mode="aspectFill" :style="{
    			opacity:isShow?'1':'0',
    			borderRadius,
    			width,
    			height,
    			transition: `opacity ${duration/1000}s ${effect}`
    			}">
    		</image>
    		
    	</view>
    </template>
    
    <script>
    	let loadTimer = null
    	import loadingImage from '../../static/loading.png'
    	import loadFailImage from '../../static/loadFail.png'
    	/**
    	 * 懒加载插件
    	 * @description 懒加载插件
    	 *
    	 * @property {String}			borderRadius		图片圆角,必须带尺寸单位
    	 * @property {String}			width				图片宽度,必须带尺寸单位(默认100%)
    	 * @property {String}			height				图片高度,必须带尺寸单位(默认100%)
    	 * @property {String}			src					图片链接,不传的话会一直是加载中状态
    	 * @property {String|Number}	minTimeOut			当图片加载过快(存在缓存)至少显示多少秒加载动画
    	 * @property {String} 			effect = [linear|ease|ease-in|ease-out|ease-in-out] 过渡效果,可以用cubic-bezier
    	 * 	@value linear 		规定以相同速度开始至结束的过渡效果(默认)
    	 * 	@value ease  		规定慢速开始,然后变快,然后慢速结束的过渡效果
    	 * 	@value ease-in 		规定以慢速开始的过渡效果
    	 * 	@value ease-out		规定以慢速结束的过渡效果
    	 * 	@value ease-in-out  规定以慢速开始和结束的过渡效果
    	 * @property {String|Number}			duration	图片加载成功后的过渡时间,单位毫秒
    	 * @property {Object}			showDistance		 当图片到屏幕哪个位置的时候开始加载,单位px,可以是负数 (默认{bottom:0})
    	 * @property {String}			loadSrc				加载中显示的图片,输入网络路径或绝对路径
    	 * @property {String}			errorSrc			加载失败显示的图片,输入网络路径或绝对路径
    	 * @event {Function} show 当图片进入页面触发
    	 * @event {Function} showSuccess 当图片完全加载完毕触发
    	 * @example <muqian-lazyLoad :src="src" width="100rpx" height="100rpx"></muqian-lazyLoad>
    	 */
    
    	export default {
    		name: "muqian-lazyLoad",
    		props: {
    			//图片圆角 必须带尺寸单位
    			borderRadius: {
    				type: String,
    				default: '0'
    			},
    			//图片宽度
    			width: {
    				type: String,
    				default: '100%'
    			},
    			height: {
    				type: String,
    				default: '100%'
    			},
    			//图片链接
    			src: {
    				type: String,
    				default: ''
    			},
    			//当图片加载过快(存在缓存)至少显示多少秒加载动画
    			minTimeOut: {
    				type: String || Number,
    				default: '300'
    			},
    			//当图片到屏幕哪个位置的时候开始加载 单位px 可以是负数
    			showDistance: {
    				type: Object,
    				default: () => {
    					bottom: 20
    				}
    			},
    			//过渡效果  linear / ease / ease-in / ease-out / ease-in-out
    			effect: {
    				type: String,
    				default: 'linear'
    			},
    			//图片加载成功后的过渡时间 单位毫秒
    			duration: {
    				type: String || Number,
    				default: '300'
    			},
    			//加载中图片
    			loadSrc: {
    				type: String,
    				default: loadingImage
    			},
    			//加载失败图片
    			errorSrc: {
    				type: String,
    				default:loadFailImage
    			}
    
    		},
    		data() {
    			return {
    				status: 0, //0加载中 1加载成功 2加载失败
    				isShow: false
    			}
    		},
    		watch: {
    			//当链接变化重新加载
    			src() {
    				if (!this.isShow) return
    				this.status = 0
    				this.isShow = false
    				this.$nextTick(() => {
    					this.status = 1
    				})
    			}
    		},
    		destroyed() {
    			//页面销毁取消监听
    			this.$emit('destroyed')
    		},
    		methods: {
    			load() {
    				if (this.minTimeOut == 0) {
    					this.isShow = true
    				}else{
    					let newTimer = new Date().getTime() - loadTimer
    					if (newTimer < this.minTimeOut) {
    						setTimeout(() => {
    							this.isShow = true
    						}, this.minTimeOut - newTimer)
    					} else {
    						this.isShow = true
    					}
    				}
    				
    				setTimeout(()=>{
    					this.$emit('showSuccess');
    				},this.duration)
    			},
    			error() {
    				this.status = 2
    				this.isShow = true
    			},
    			init(){
    				let intersectionObserver = uni.createIntersectionObserver(this)
    				let load = false
    				//当图片加载完的时候取消监听
    				this.$once('destroyed', () => {
    					intersectionObserver.disconnect()
    				})
    				intersectionObserver.relativeToViewport(this.showDistance).observe('.muqain-load', (res) => {
    					if (!load && res.intersectionRatio == 0) {
    						load = true
    						return
    					}
    					this.$emit('show');
    					load = true
    					this.status = 1
    					loadTimer = new Date().getTime()
    					intersectionObserver.disconnect()
    				})
    			}
    		}
    
    	}
    </script>
    
    <style lang="scss" scoped>
    	.muqian-content {
    		overflow: hidden;
    		position: relative;
    		.muqian-image {
    			display: block;
    			will-change: transform;
    		}
    
    		.muqain-load {
    			position: absolute;
    			left: 0;
    			top: 0;
    		}
    	}
    </style>
    
    
    

三、使用方法

// 示例
<lazyLoad src="图片链接" width="100rpx" height="100rpx" borderRadius="50%"></lazyLoad>

四、注意事项

  • 宽高是要带单位

  • 此插件只支持固定宽高的图片

  • 本插件使用intersectionObserver API监听节点的相交情况实现懒加载

  • 组件点击事件建议使用@click.native绑定

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要实现下拉框懒加载和搜索,可以考虑以下步骤: 1. 在页面中添加一个输入框和一个下拉框组件。 2. 在下拉框组件的数据源中只初始化一部分数据,比如10条。 3. 当用户滚动到下拉框的底部时,触发下拉框的on-scrolltolower事件,在该事件中加载更多的数据并添加到数据源中。 4. 在输入框的输入事件中,获取输入的关键字,进行模糊匹配,并更新下拉框的数据源。 5. 当用户选择下拉框中的某一项时,将选中的值显示在输入框中。 实现代码如下: ```html <template> <view> <input type="text" placeholder="请输入搜索关键字" @input="onInput" /> <scroll-view scroll-y style="height: 300rpx;" @scrolltolower="onScrollToLower"> <view v-for="(item, index) in dataList" :key="index" @click="onItemClick(item)"> {{item.text}} </view> </scroll-view> </view> </template> <script> export default { data() { return { dataList: [], // 下拉框数据源 pageIndex: 0, // 当前页码 pageSize: 10, // 每页条数 keyword: '', // 关键字 }; }, onReady() { // 初始化数据 this.loadData(); }, methods: { // 加载数据 loadData() { // 模拟异步加载数据 setTimeout(() => { const data = []; for (let i = 0; i < this.pageSize; i++) { data.push({ id: this.pageIndex * this.pageSize + i + 1, text: `选项${this.pageIndex * this.pageSize + i + 1}`, }); } this.dataList = this.dataList.concat(data); this.pageIndex++; }, 1000); }, // 滚动到底部触发 onScrollToLower() { this.loadData(); }, // 输入框输入事件 onInput(e) { this.keyword = e.detail.value; this.filterData(); }, // 数据筛选 filterData() { const reg = new RegExp(this.keyword, 'g'); this.dataList = this.dataList.filter(item => reg.test(item.text)); }, // 下拉框项点击事件 onItemClick(item) { console.log('选中了:', item); }, }, }; </script> ``` 注意:为了方便演示,这里的数据是通过setTimeout模拟异步加载的,实际开发中需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酱爆 Crazy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值