翻看element-ui源码,会发现大图预览是一个组件image-viewer,但直接用有很多坑,我们可以基于此撸一个简易图片查看器。
image-viewer组件我们能用到的prop分别是zIndex
、urlList
、onClose
。
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
},
}
总结
这样就可以免去安装其它插件了。除了预览功能,还可以基于此扩展更多功能。