背景:
使用uniapp框架在做h5项目时,领导要求预览图片时不能一次性加载完所有的图片,需要看一张加载一张,这样用户不费流量,优化h5的性能。
首先uniapp官网实现图片预览使用的是uni.preview api,但是这样传的urls数组,在点击图片进行预览时一次性加载了所有的图片。
所以要实现图片预览,点击一张加载这张图片需要自已写预览组件。
这里用到的是swiper组件来进行预览功能。
1、新建公共组件 previewImage.vue
<template>
<view class="previewImg" v-if="show" @touchmove.stop.prevent :class="{
'pc-full':!$util.isMobile(),'full':$util.isMobile()}">
<view class="mask" @click="close" :class="{
'pc-full':!$util.isMobile(),'full':$util.isMobile()}">
<swiper class="mask-swiper" :current="index" @change="swiperChange" :disable-touch="false" :class="{
'pc-full':!$util.isMobile(),'full':$util.isMobile()}">
<swiper-item v-for="(img, i) in pageList" :key="i">
<image class="mask-swiper-img" :src="img" mode="aspectFit" :class="{
'pc-full':!$util.isMobile(),'full':$util.isMobile()}"/>
</swiper-item>
</swiper>
</view>
<view class="page" v-if="imgs.length > 0">
{
{ index + 1 }} / {
{ imgs.length }}
</view>
<view class="close-btn" @click.stop="close()">
<icon type="clear" size="30" />
</view>
</view>
</template>
<script>
export default {
name: 'previewImage',
props: {
// 图片数组,由父组件传值
imgs: {
type: Array,
default: () => {
return [];
}
},
},
data() {
return {
show: false, // 展示预览组件
index: 0,
pageList: [],
};
},
methods: {
swiperChange(e) {
let
oldPageIndex = this.index, // 之前展示的页面索引
newPageIndex = e.detail.current; // 滑动后新展示的页面索引
// 判断是否由用户触摸引起的
if (e.detail.source == 'touch') {
// 判断滑动方向
if (oldPageIndex < newPageIndex) {
// 向左滑
// 判断是否到最后一张,并且地址信息是否为空
if (newPageIndex < this.imgs.length - 1 && !this.pageList[newPageIndex + 1]) {
this.pageList[newPageIndex + 1] = this.imgs[newPageIndex + 1];
}
this.index = newPageIndex;
} else if (oldPageIndex > newPageIndex) {
// 向右滑
// 判断是否到第一张
if (newPageIndex < this.imgs.length - 1 && !this.pageList[newPageIndex - 1]) {
this.pageList[newPageIndex - 1] = this.imgs[newPageIndex - 1];
}
this.index = newPageIndex;
}
}
},
open(e) {
const _this = this;
_this.index = e;
_this.show = true;
// 根据图片总数,创建需要渲染的空数组
let pageList = new Array(_this.imgs.length).fill('');
// 初始化渲染数组,载入当前图片,并且预载入下一张图片
// 如果当前不是在第一张,预载入当前图片+下一张图片+上一张图片
// 如果当前是第一张,预载入下一张图片
// 如果当前是最后一张,预载入上一张图片
pageList[_this.index] = _this.imgs[_this.index];
if(_this.index === 0 && _this.imgs.length > _this.index + 1){
pageList[_this.index + 1] = _this.imgs[_this.index + 1];
}else if(_this.index !== 0 && _this.index + 1 > 0 && _this.index + 1 < _this.imgs.length){
pageList[_this.index + 1] = _this.imgs[_this.index + 1];
pageList[_this.index - 1] = _this.imgs[_this.index - 1];
}else if(_this.imgs.length = _this.index + 1){
pageList[_this.index - 1] = _this.imgs[_this.index - 1];
}
// 渲染页面
_this.pageList = pageList;
},
//关闭预览
close() {
this.show = false;
this.index = 0;
}
}
};
</script>
2、调用预览组件
新建父组件index.vue
<view class="img-item" v-for="(img, imgIndex) in files" :key="imgIndex" @click.stop="previewImage(imgIndex)">
<img :src="img.imgurl" />
</view>
<preview-image ref="previewImage" :imgs="imgs"></preview-image>
import previewImage from '@/components/previewImage.vue';
export default {
components: {
previewImage
},
data() {
return {
files:[], // 循坏渲染到页面的图片
imgs:[], // 进行预览的图片数组字符串
}
},
methods:{
// 预览事件,点击当前图片,将图片索引传给事件
previewImage(index){
_this.$nextTick(function(){
// 执行预览子组件的open事件
_this.$refs.previewImage.open(index);
});
}
}
}