从0到1封装一个image/pdf预览组件

news/2024/12/22 13:14:28/

目录结构

content.vue
<template><div class="no-content-block"><i class="iconfont icondocument large-file" /><div class="text-wrapper">{{ t('__ui__.siPreview.previewSupported') }}</div><div class="buttons-default" @click="donwload(url)"><i class="iconfont el-icon-download" /><div class="button-name">{{ t('__ui__.siPreview.downloadAttachment') }}</div></div></div>
</template><script>
import Locale from '../../../../mixins/locale'
export default {name: 'BlankContent',mixins: [Locale],inject: ['app'],props: {url: {type: String,default: ''}},methods: {donwload(url) {this.app.download()window.open(url, '_blank')}}
}
</script>
previewContent.vue
<template><div class="pre-view-content"><div class="buttons-icons-con" @click="donwload(fileUrl)"><i class="iconfont el-icon-download" /></div><div class="buttons-icons-set" @click="closeDialogue(fileType)"><i class="iconfont el-icon-close" /></div></div>
</template><script>
export default {name: 'PreviewContent',inject: ['app'],props: {fileUrl: {type: String,default: ''},fileType: {type: String,default: ''}},methods: {donwload(url) {this.app.donwload(url)},closeDialogue(type) {this.app.closeDialogue(type)}}
}
</script>
index.js
/*Exposure to the outside worldfileUrl、Other parameters;Transfer datafileUrl address;openLoad Yes, it's all function calls;Exclusive introductionimport Vue from 'vue'import { FilePreview } from '@payermax/components-manage-base'Vue.use(FilePreview)(= ̄ω ̄=) file you use this componentthis.$filePreview('xxx');*/
// import Vue from 'vue'
import _component from './index.vue'
import { prefix } from '../../../const'const FilePreview = {install(Vue, options) {Vue.prototype.$filePreview = (url, downLoadCallback, closeCallback) => {// Builderconst ComponentInstance = Vue.extend({render(h) {return h(_component, {props: {fileUrl: url,downloadFile: downLoadCallback,closeFile: closeCallback,openLoad: true}})}})// Create a singletonconst instance = new ComponentInstance().$mount()document.body.appendChild(instance.$el)}Vue.component(`${prefix}${_component.name}`, _component)}
}export default FilePreview

index.js 代码解释

当前代码定义了一个名为 $filePreview 的 Vue 实例方法,该方法用于在页面中预览文件。以下是对代码的详细解释:

  1. 方法定义

    javascript

    Vue.prototype.$filePreview = (url, downLoadCallback, closeCallback) => {//...
    }
    

    这里定义了一个 Vue 实例方法 $filePreview,它接受三个参数:url(文件的 URL 地址),downLoadCallback(下载文件的回调函数),closeCallback(关闭文件预览的回调函数)。

  2. 组件实例化

    javascript

      const ComponentInstance = Vue.extend({render(h) {return h(_component, {props: {fileUrl: url,downloadFile: downLoadCallback,closeFile: closeCallback,openLoad: true}})}})
    

    这里使用 Vue.extend 创建了一个 Vue 组件的子类 ComponentInstance,并在其 render 函数中使用 h 函数渲染 _component 组件,并传递了四个属性:fileUrldownloadFilecloseFileopenLoad

  3. 创建实例并挂载

    javascript

      const instance = new ComponentInstance().$mount()document.body.appendChild(instance.$el)
    

    这里创建了 ComponentInstance 的实例 instance,并将其挂载到一个新的 DOM 元素上,然后将这个 DOM 元素添加到文档的 body 中。

总结来说,$filePreview 方法通过创建一个 Vue 组件实例,并将其渲染到页面上,实现了文件预览的功能。用户可以通过传递文件的 URL 和相应的回调函数来使用这个方法。

index.vue
<template><div ref="filePreviewContainer" class="file-preview-container"><div class="download-card"><div class="preview-wrap"><div v-if="openLoad" /><div v-else class="click-default"><!-- Click arera --><div @click="previewFile()"><div v-if="!hasSlot" /><slot v-else /></div></div><!--  Preview types --><template v-if="pdfContainerVisible && fileType == 'pdf'"><div><div id="pdf-container" /><div v-loading="loading" class="pdf-loading" /><div class="pdf-download"><div class="pdf-download-container"><PreviewContent :file-url="fileUrl" :file-type="fileType" /></div></div></div></template><div v-if="imageVisible && fileType == 'image'"><div class="other-container"><div class="header"><PreviewContent :file-url="fileUrl" :file-type="fileType" /></div><div class="other-containe-content"><img loading="lazy" alt="" :src="fileUrl"></div></div></div><div v-if="otherVisible" class="other-container"><div class="header"><PreviewContent :file-url="fileUrl" :file-type="fileType" /></div><div class="other-containe-content"><div v-if="openLoad" class="no-content-block"><i class="iconfont icondocument large-file" /></div><BlankContent v-else :url="fileUrl" /></div></div></div></div></div>
</template><script>import PDFObject from 'pdfobject'
import BlankContent from './components/content.vue'
import PreviewContent from './components/previewContent.vue'import Locale from '../../../mixins/locale'const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']
const pdfExtensions = ['pdf']
const SCOPE_NAME = 'FilePreview'export default {name: SCOPE_NAME,components: {BlankContent,PreviewContent},mixins: [Locale],provide() {return {app: this}},inheritAttrs: false,props: {fileUrl: {type: String,default: ''},closeFile: {type: Function,default: () => { }},downloadFile: {type: Function,default: () => { }},openLoad: {type: Boolean,default: false}},data() {return {fileType: '',pdfContainerVisible: false,imageVisible: false,otherVisible: false,loading: false,hasSlot: false}},mounted() {this.init()this.mountPlugIn()},methods: {mountPlugIn() {if (this.openLoad) {this.previewFile()}},init() {this.justFileType()this.checkSlots()},checkSlots() {if (this.$slots.default) {this.hasSlot = true} else {this.hasSlot = false}},justFileType() {const extension = this.fileUrl.split('.').pop().toLowerCase() || ''if (imageExtensions.includes(extension)) {this.fileType = 'image'} else if (pdfExtensions.includes(extension)) {this.fileType = 'pdf'} else {this.fileType = 'other'}},close() {this.$emit('closeFile')this.openLoad && this.closeFile()this.openLoad && this.dealPluginPreviewNode()},download() {this.$emit('downloadFile')this.openLoad && this.downloadFile()this.openLoad && this.dealPluginPreviewNode()},dealPluginPreviewNode() {var containers = document.querySelectorAll('.file-preview-container')if (containers.length > 0) {var lastContainer = containers[containers.length - 1]var parent = lastContainer.parentNodeparent.removeChild(lastContainer)}},previewFile() {switch (this.fileType) {case 'pdf':this.pdfPreview(this.fileUrl)breakcase 'image':this.imagePreview(this.fileUrl)breakcase 'other':this.otherPreview()breakdefault:break}},async pdfPreview(fileUrl) {this.loading = truetry {const response = await fetch(fileUrl)const status = response?.status || ''if (status === 200) {this.pdfContainerVisible = truethis.loading = falsethis.$nextTick(() => {let url = ''if (fileUrl.startsWith('http://')) {url = fileUrl.substring(5)} else if (fileUrl.startsWith('https://')) {url = fileUrl.substring(6)} else {url = fileUrl}PDFObject.embed(url, '#pdf-container', {width: '100%'})})} else {this.loading = falsethis.otherVisible = true}} catch (error) {this.loading = falsethis.otherVisible = true}},imagePreview(fileUrl) {this.loading = truethis.checkImageAccessibility(fileUrl, (accessible) => {if (accessible) {this.imageVisible = true} else {this.otherVisible = true}this.loading = false})},checkImageAccessibility(url, callback) {const img = new Image()img.onload = function() {callback(true)}img.onerror = function() {callback(false)}img.src = url},otherPreview() {this.otherVisible = true},closeDialogue(type) {switch (type) {case 'pdf':this.pdfContainerVisible = falsethis.close()breakcase 'image':this.imageVisible = falsethis.close()breakcase 'other':this.otherVisible = falsethis.close()breakdefault:break}},donwload(url) {this.download()window.open(url, '_blank')}}
}
</script>
全局引入
import locale from './locale'
import { prefix } from './const'import FilePreview from './src/Other/FilePreview'const components = [FilePreview
]export {FilePreview
}function install(Vue, options = {}) {locale.i18n(options.i18n)components.forEach((component) => {console.log(component.name, component)if (component.install) {component.install(Vue, options)} else {Vue.component(`${prefix}${component.name}`, component)}})
}export default install
按需引入

Text.vue

         <el-row><el-col :span="6"><h2>图片(默认)</h2><m-FilePreview:file-url="fileUrl"@closeFile="closeTest"@downloadFile="downloadTest"/></el-col><el-col :span="6"><h2>其他类文件(默认)</h2><m-FilePreview:file-url="otherFileUrl"@closeFile="closeTest"@downloadFile="downloadTest"/></el-col><el-col :span="6"><h2>PDF文件(默认)</h2><m-FilePreview:file-url="PdfUrl"@closeFile="closeTest"@downloadFile="downloadTest"/></el-col></el-row><el-row><el-col :span="6"><h2>图片(自定义按钮样式)</h2><m-FilePreview:file-url="fileUrl"@closeFile="closeTest"@downloadFile="downloadTest"><div class="haoren"><el-button type="primary" plain>图片按钮</el-button></div></m-FilePreview></el-col><el-col :span="6"><h2>其他类文件(自定义按钮样式)</h2><m-FilePreview:file-url="otherFileUrl"@closeFile="closeTest"@downloadFile="downloadTest"><div class="haoren"><el-button type="success" plain>无法预览的文件</el-button></div></m-FilePreview></el-col><el-col :span="6"><h2>PDF文件 (自定义按钮样式)</h2><m-FilePreview:file-url="PdfUrl"@closeFile="closeTest"@downloadFile="downloadTest"><divstyle="color:red;width:200px;height: 80px;background-color: aquamarine;display: flex;font-weight: 700;justify-content: center;align-items: center;border-radius: 12px;cursor: pointer;">PDF预览演示</div></m-FilePreview></el-col></el-row><el-row style="margin-top: 80px;"><el-col :span="6"><h2>图片(函数式调用)</h2><div @click="TestMess('img')"><el-button type="primary">函数式预览图片</el-button></div></el-col><el-col :span="6"><h2>PDF (函数式调用)</h2><div @click="TestMess('pdf')"><el-button type="info">函数式预览PDF</el-button></div></el-col><el-col :span="6"><h2>其他类型</h2><div @click="TestMess('other')"><button>函数式调用其他类型</button></div></el-col></el-row>
 fileUrl: 'https://s3.ap-s%29.gif',PdfUrl: 'https://s3.ap-south36596/NL2SQL.pdf',otherFileUrl: 'https://gimg4.baidu.com/poster/f',
  TestMess(val) {if (val === 'img') {this.$filePreview(this.fileUrl, this.downloadTest, this.closeTest)} else if (val === 'pdf') {this.$filePreview(this.PdfUrl, () => { console.log('click download!') }, () => { console.log('close window!') })} else {this.$filePreview(this.otherFileUrl, () => { console.log('click download!') }, () => { console.log('close window!') })}}
代码使用


http://www.ppmy.cn/news/1539434.html

相关文章

基于ffmpeg实现多路rtsp拉流解码为yuv420p

一&#xff1a;前言 FFmpeg 是一个非常强大的多媒体框架&#xff0c;它可以用来处理视频和音频数据。它包括了命令行工具 ffmpeg、ffplay、ffprobe 等&#xff0c;以及一套可以用来开发多媒体应用的库&#xff08;libavcodec、libavformat、libavutil、libswscale 等&#xff0…

LangChain使用Prompt02

1.设置提示 from langchain.prompts import ChatPromptTemplate prompt_template ChatPromptTemplate.from_messages([("system", "你是一位专业的翻译&#xff0c;能够将{input_language}翻译成{output_language}&#xff0c;并且输出文本会根据用户要求的任…

云原生周刊:优化 Uber 的持续部署丨2024.10.14

开源项目推荐 Cog Cog 是将机器学习模型打包到容器的工具。可通过配置将机器学习模型所需的环境和依赖&#xff0c;自动打包到容器里方便部署&#xff0c;让你不再为编写 Docker 文件和 CUDA 而痛苦&#xff0c;还能自动启动 HTTP 接口服务方便调用。 KnowStreaming KnowSt…

基于FreeRTOS的LWIP移植

目录 前言一、移植准备工作二、以太网固件库与驱动2.1 固件库文件添加2.2 库文件修改2.3 添加网卡驱动 三、LWIP 数据包和网络接口管理3.1 添加LWIP源文件3.2 Lwip文件修改3.2.1 修改cc.h3.2.2 修改lwipopts.h3.2.3 修改icmp.c3.2.4 修改sys_arch.h和sys_arch.c3.2.5 修改ether…

架构设计笔记-18-安全架构设计理论与实践

知识要点 常见的安全威胁&#xff1a; 信息泄露&#xff1a;信息被泄露或透露给某个非授权的实体。破坏信息的完整性&#xff1a;数据被非授权地进行增删、修改或破坏而受到损失。拒绝服务&#xff1a;对信息或其他资源的合法访问被无条件地阻止。攻击者向服务器发送大量垃圾…

【浏览器】如何正确使用Microsoft Edge

1、清理主页广告 如今的Microsoft Edge 浏览器 主页太乱了&#xff0c;各种广告推送&#xff0c;点右上角⚙️设置&#xff0c;把快速链接、网站导航、信息提要、背景等全部关闭。这样你就能得到一个超级清爽的主页。 网站导航       关闭 …

mysql--数据表的操作

说明&#xff1a;filed为列名 关于数据表的操作 目录 1、创建表 2、查看表结构 &#xff08;1&#xff09;显示表结构 &#xff08;2&#xff09;显示具体表信息 3、修改表结构 &#xff08;1&#xff09;删除表 &#xff08;2&#xff09;修改表名 &#xff08;3&am…

Dockerr安装Oracle以及使用DBeaver连接

拉取镜像 pull container-registry.oracle.com/database/free:latest 创建容器 说明一下我现在的最新版本是23 docker run -d --name oracle23i -h xrilang -p 1521:1521 container-registry.oracle.com/database/free:latest 查看日志 docker logs oracle23i 设置密码 因为创建…