背景
在后台管理系统中,一些预览图片的场景,通常都是使用 `el-image-viewer` 去实现,但是如果多个地方都需要预览图片,又要重复的去写 `el-image-viewer` 以及一些重复的和预览相关的代码。
可以把预览图片的组件放在根文件,把通用的预览相关的代码放在状态管理,哪里需要预览图片,就引入调用预览方法,让根组件的预览组件预览图片。
实现
1. 状态管理用的pinia,新建preview模块文件
// /stores/modules/preview.jsimport { defineStore } from "pinia";export const PreviewStore = defineStore({id: "PreviewStore",state: () => {return {// 记录图片预览数据imageViewer: { show: false, // 控制图片的显现url: "", // 预览的图片路径close: () => {} // 关闭的回调方法}}},actions: {// 打开图片预览的弹窗openImageViewer({ url, close }: { url: string; close?: Function }) {this.imageViewer = {show: true,url,close: async () => {close && (await close());this.imageViewer.show = false;}};}}
});
2.对 el-image-viewer 进行了二次封装,增加了点击遮罩层关闭预览方法
// /components/modules/CImageViewer/index.vue<template><el-image-viewer v-bind="$attrs" :url-list="[`${baseUrl}${imageViewerUrl}`]" @close="imageViewerClose" />
</template>
<script setup lang="ts">
import { onMounted, ref, nextTick, onBeforeUnmount, computed } from "vue";
import { windowOrigin } from "@/utils/util";
import { PreviewStore } from "@/stores/modules/preview";const baseUrl = windowOrigin(); // 基础路径
const previewStore = PreviewStore();
const imageViewerUrl = computed(() => previewStore.imageViewer.url);
const imageViewerClose = computed(() => previewStore.imageViewer.close);
onMounted(() => {nextTick(() => {// 获取预览的遮罩层mask.value = document.querySelector(".el-image-viewer__mask") as HTMLDivElement;if (mask.value) {// 遮罩层增加点击事件,关闭预览mask.value.addEventListener("click", imageViewerClose.value);}});
});
onBeforeUnmount(() => {if (mask.value) {// 遮罩层增加点击事件,关闭预览previewStore.imageViewer.close();mask.value.removeEventListener("click", previewStore.imageViewer.close);}
});
</script>
3. 在根组件App.vue 使用 CImageViewer 预览图片组件
// App.vue<template>... 其他文件<!-- 全局的图片预览组件 --><c-image-viewer v-if="imageViewerVisible"></c-image-viewer>
</template><script setup lang="ts">
import { computed } from "vue";
import { PreviewStore } from "@/stores/modules/preview";import CImageViewer from "@/components/modules/CImageViewer/index.vue";const previewStore = PreviewStore();
// 控制图片预览组件显现的变量
const imageViewerVisible = computed(() => previewStore.imageViewer.show);</script>
4. 调用预览图片组件
// 需要预览图片的文件<template><div class="page"><imgclass="imgUrl"v-for="(url, index) in imageList(',')":key="index":src="url"@click="handlePicturePreview(url)"/></div>
</template>
<script setup lang="ts">
import { PreviewStore } from "@/stores/modules/preview";// ===========【 查看图片 】===========
const previewStore = PreviewStore();
const handlePicturePreview = (url: string) => {previewStore.openImageViewer({ url });
};
</script>
总结
其实就是把根组件的图片预览显现,和调用预览方法 都是交给状态管理控制的,这样就用el-image-viewer 实现全局预览图片的功能。