uni-app 图片懒加载
性能
实现图片懒加载,并且显示数组中,始终只有 3 张图片,高低滑动减少的同时,删除最开始的那一张。能够指定从总图片的第几张开始加载。
思路
要实现高低滑动时的动画成果,我这里用到是 uni-app 自带 swiper 组件。同时为了解决减少或删除数组时,会从新渲染,导致动画成果未实现,所以用的是 animationfinish
页面加载后触发的事件。
要实现高低滑动时,动画执行结束之后,要把执行后的那张图片,始终保持在两头地位。此处,就用到了 serper 组件中的 current,当滑倒第 3 或者第 1 张时,给 current 赋值,使显示的图片始终在第二张的地位。同时滑动增加的同时,也要删除掉最开始的那一张
步骤
swiper 组件应用
<swiper vertical="true"
:current="atPresentNode.swiperIndex"
@animationfinish="slideSwiper">
<swiper-item v-for="item,index in swiperItems"
:key="index">
<view>{{item}}</view>
</swiper-item>
</swiper>
初始化显示页面
当总图片数组索引位为 0 时,则定位到第一张图片。当总图片数组索引位 >0 时,则定位到第二张图片
let swiperIndex = index ? 1 : 0 //seriperIndex(显示数组索引位)
itemsIndex = index ? index - 1 : 0 // itemsIndex(总图片数组索引位),- 1 是数组从 0 开始
let minLength = Math.min(2, this.items.length - index) // 避免总索引位大于总的数组长
挪动页面
1. 判断上滑还是下滑
通过 swiper 组件 current,能够失去以后页面索引值,减去未滑动前的页面索引值。大于 0 则是向下滑动,小于 0 则是向上滑动。
let currentNum = event.target.current - this.atPresentNode.swiperIndex
2. 下滑时
判断以后页面图片是两头的那一张, 并且总数组长度大于页面索引值 + 1 时,加载第四张图片。
this.atPresentNode.swiperIndex >= 2 && this.items.length > this.atPresentNode.itemsIndex + 1
setTimeout 是为了保障删除时,数组是曾经增加进去了的
this.atPresentNode.swiperIndex = 1 保障滑动后的图片始终在两头地位
this.swiperItems.push(this.items[this.atPresentNode.itemsIndex + 1])
setTimeout(() => {
this.atPresentNode.swiperIndex = 1
this.swiperItems.shift()}, 0)
上滑时
判断滑动之后是否在第一张的地位,并且 总索引位大于 0
this.atPresentNode.swiperIndex <= 0 && this.atPresentNode.itemsIndex > 0
此处先删除后增加是因为先在头部增加时,会扭转显示图片绝对于数组的地位,显示图片的地位就向下延后了一位。所以为了防止这种状况,故而先删除,再增加到头部
this.swiperItems.pop()
setTimeout(() => {
this.atPresentNode.swiperIndex = 1
this.swiperItems.unshift(this.items[this.atPresentNode.itemsIndex - 1])
}, 0)
残缺代码
data () {
return {
index: 0, // 从总数组第几位开始
items: [], // 总数组
swiperItems: [], // 显示数组
atPresentNode: {
swiperIndex: 0, // 显示数组索引位
itemsIndex: 0, // 总数组索引位
},
}
},
created () {this.initSwiperItems(this.index)
},
methods: {initSwiperItems (index) {this.swiperItems = []
if (this.items.length <= 0) {return}
let swiperIndex = index ? 1 : 0
index = +index ? +index - 1 : 0
this.atPresentNode = {
swiperIndex,
itemsIndex: index,
}
let minLength = Math.min(2, this.items.length - index)
for (let i = 0; i <= minLength; i++) {this.items[index + i] && this.swiperItems.push(this.items[index + i])
}
this.atPresentNode.swiperIndex == 1 && (this.atPresentNode.itemsIndex = this.atPresentNode.itemsIndex + 1) // 当从第二张显示时,总数组索引位也加一
},
slideSwiper (event) {
let currentNum = event.target.current - this.atPresentNode.swiperIndex
if ((this.items.length <= this.atPresentNode.itemsIndex + 1 || this.atPresentNode.itemsIndex == 0) && currentNum == 0) {uni.showToast({ title: '曾经没有更多的数据了', icon: 'none'})
return
}
if (currentNum > 0) {
this.atPresentNode.swiperIndex++ // 为了和 current 同步,所以此处须要 ++
this.atPresentNode.itemsIndex++
if (this.atPresentNode.swiperIndex >= 2 && this.items.length > this.atPresentNode.itemsIndex + 1) {this.swiperItems.push(this.items[this.atPresentNode.itemsIndex + 1])
setTimeout(() => {
this.atPresentNode.swiperIndex = 1
this.swiperItems.shift()}, 0)
}
}
if (currentNum < 0) {
this.atPresentNode.swiperIndex-- // 为了和 current 同步,所以此处须要 --
this.atPresentNode.itemsIndex--
if (this.atPresentNode.swiperIndex <= 0 && this.atPresentNode.itemsIndex > 0) {this.swiperItems.pop()
setTimeout(() => {
this.atPresentNode.swiperIndex = 1
this.swiperItems.unshift(this.items[this.atPresentNode.itemsIndex - 1])
}, 0)
}
}
}
}