uniapp swiper realizes picture preview, previews two pictures before and after loading one picture, and realizes performance optimization

background:

When using the uniapp framework to work on the h5 project, the leader requested that when previewing pictures, not all the pictures can be loaded at one time, but one needs to be viewed and loaded one by one, so that users do not need to spend traffic and optimize the performance of h5.
First of all, the uniapp official website uses the uni.preview api to realize the picture preview, but the urls array passed in this way loads all the pictures at once when clicking the picture to preview.
So to realize the image preview, you need to write the preview component yourself when you click a picture to load the image.
The swiper component is used here for the preview function.

1. Create a new public component 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. Call the preview component

New parent component 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);
	        });
		}	
	}
}

Guess you like

Origin blog.csdn.net/qiaoqiaohong/article/details/123270209