用element-ui撸一个简易图片查看器

1,145 阅读1分钟

翻看element-ui源码,会发现大图预览是一个组件image-viewer,但直接用有很多坑,我们可以基于此撸一个简易图片查看器。

image-viewer组件我们能用到的prop分别是zIndexurlListonClose

zIndex:z-index样式,默认是2000。

urlList:就是和el-image的previewSrcList的用法一样,数组类型。

onClose:关闭查看器的回调。

完整代码

<template>
    <el-image-viewer v-if="visible" :on-close="closeViewer" :url-list="urlList" :z-index="zIndex" />
</template>

<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
export default{
    name: 'ComImageViewer',
    components: {
        ElImageViewer
    },
    props: {
        visible: {
            type: Boolean,
            default: false
        },
        // 多个图片时,数组的最后一个值就是显示图片的索引 必须是Number类型,空则会默认第一张
        url: {
            type: [Array, String],
            default: () => []
        },
        zIndex: {
            type: Number,
            default: 2000
        },
    },
    data(){
        return {

        }
    },
    computed: {
        urlList() {
            let url = this.url
            if (Array.isArray(url)) {
                let index = url[url.length - 1]
                if (Number.isInteger(index)) {
                    url.pop()
                    return this.getPrivewImages(index, url)
                } else {
                    return url;
                }
            } else {
                return [url];
            }
        }
    },
    watch: {
        visible: {
            handler(val) {
                if (val) {
                    this.stopMove()
                    document.addEventListener('click', this.handleCliskMask, true)
                } else {
                    this.move()
                    document.removeEventListener('click', this.handleCliskMask, true)
                }
            },
            deep: true
        }
    },
    methods: {
        closeViewer() {
            this.$emit('onClose');
            this.$emit('update:visible', false);
        },
        // 预览对应当前图片列表
        getPrivewImages(index, imgArr) {
            let tempImgList = imgArr;
            if (index == 0) return tempImgList;
            // 调整图片顺序,把当前图片放在第一位
            return tempImgList.slice(index).concat(tempImgList.slice(0, index));
        },
         // 禁止页面滚动
        stopMove () {
            let m = function(e){e.preventDefault()}
            document.body.style.overflow = 'hidden'
            document.addEventListener("touchmove", m, { passive:false })
        },
        // 开启页面滚动
        move () {
            let m =function(e){e.preventDefault()}
            document.body.style.overflow = 'auto'
            document.removeEventListener("touchmove", m, { passive:true })
        },
        // 监听遮罩层
        handleCliskMask(e) {
            if(document.querySelector('.el-image-viewer__mask').contains(e.target)){
                this.closeViewer()
            }
        }
    }
}
</script>

代码解读

    getPrivewImages(index, imgArr) {
        let tempImgList = imgArr;
        if (index == 0) return tempImgList;
        return tempImgList.slice(index).concat(tempImgList.slice(0, index));
    }

urlList传多张图时,图片是从第一张图开始显示的,而实际上我们想要的效果是点击当前图片显示当前对应的大图。原理是根据当前图片index索引找到当前大图并调整到图片数组的第一位,就能够显示当前对应的大图。

    urlList() {
        let url = this.url
        if (Array.isArray(url)) {
            let index = url[url.length - 1]
            if (Number.isInteger(index)) {
                url.pop()
                return this.getPrivewImages(index, url)
            } else {
                return url;
            }
        } else {
            return [url];
        }
    }

如何接收index索引,读者可以自由设计,我这里是将数组的最后一个值用于传index索引,比如这样[url,url,index]

使用方式

这里我就不写那么详细了,使用比较简单。

<image v-for="(item, index) in images" :key="index" :src="item" @click="handlePreviewImage(index)">
<ComImageViewer :visible.sync="showViewer" :url="url" ></ComImageViewer>

data() {
    return {
    	images: [],
        showViewer: false,
        url: ''
    }
},
methods: {
    handlePreviewImage(index) {
        this.url = [...images, index]
        this.showViewer = true
    },
}

总结

这样就可以免去安装其它插件了。除了预览功能,还可以基于此扩展更多功能。