当前位置: 首页 > news >正文

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

iShot_2024-10-14_16.47.10

目录结构

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!') })}}
代码使用

相关文章:

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

iShot_2024-10-14_16.47.10 目录结构 content.vue <template><div class"no-content-block"><i class"iconfont icondocument large-file" /><div class"text-wrapper">{{ t(__ui__.siPreview.previewSupported) }}<…...

Android build子系统(02)Ninja语法与复杂依赖构建解读

说明&#xff1a;本文将解读Ninja构建系统的基础语法和应用&#xff0c;同时给出一些示例便于理解和学习&#xff1b;给出一个复杂构建的基础demo&#xff0c;通过这个demo的分析理解复杂构建的内在逻辑和build.ninja编写法则&#xff1b;最后扩展之前Android Framework中构建b…...

JavaScript的第三天

目录 JS中的循环&#xff0c;使某些代码重复执行 一、for循环&#xff1a;重复执行某段代码&#xff0c;通常用于计数 1、for的语法结构 2、代码解析 3、代码尝试 4、循环重复相同的代码&#xff0c;可以让用户控制输出的次数&#xff08;对该变量进行遍历&#xff09; 5、循环…...

初识git · 有关模型

目录 前言&#xff1a; 有关开发模型 前言&#xff1a; 其实文章更新到这里的时候&#xff0c;我们已经学习了可以满足我们日常生活中的基本需求的指令了&#xff0c;但是为什么要更新本篇文章呢&#xff1f;是因为实际生活中我们对于开发工作&#xff0c;运维工作&#xff…...

基于SpringBoot+Vue+uniapp的海产品加工销售一体化管理系统的详细设计和实现(源码+lw+部署文档+讲解等)

详细视频演示 请联系我获取更详细的视频演示 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…...

解锁机器人视觉与人工智能的潜力,从“盲人机器”改造成有视觉能力的机器人(下)

机器视觉产业链全景回顾 视觉引导机器人生态系统或产业链分为三个层次。 上游&#xff08;供应商&#xff09; 该机器人视觉系统的上游包括使其得以运行的硬件和软件提供商。硬件提供商提供工业相机、图像采集卡、图像处理器、光源设备&#xff08;LED&#xff09;、镜头、光…...

CORS预检请求配置流程图 srpingboot和uniapp

首先要会判断预检请求 还是简单请求 简单请求 预检请求 #mermaid-svg-1R9nYRa7P9Pll4AK {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-1R9nYRa7P9Pll4AK .error-icon{fill:#552222;}#mermaid-svg-1R9nYRa7P9Pll4…...

用Spring AI 做智能客服,基于私有知识库和RAG技术

Java智能客服系统运用RAG技术提升答疑精准度 基于Spring ai 的 RAG&#xff08;检索增强生成&#xff09;技术&#xff0c;Java智能客服系统能够利用私有知识库中的信息提供更准确的答疑服务。 它的核心思路是&#xff1a; 首先&#xff0c;将客服QA以Word形式导入到系统中&…...

TemporalBench:一个专注于细粒度时间理解的多模态视频理解的新基准。

2024-10-15&#xff0c;由威斯康星大学麦迪逊分校、微软研究院雷德蒙德等机构联合创建了TemporalBench&#xff0c;它通过大约10K个视频问答对&#xff0c;提供了一个独特的测试平台&#xff0c;用以评估各种时间理解和推理能力&#xff0c;如动作频率、运动幅度、事件顺序等。…...

网友提问:网上申请流量卡不通过怎么办?

网上申请流量卡不通过怎么办&#xff1f;网上办理流量卡不通过&#xff0c;说明你不符合办理此套餐的要求&#xff0c;可以选择其他套餐&#xff0c;或者其他运营商的流量卡申请试试。 我们不管是在京*、淘*、拼**哪个网站申请的流量卡&#xff0c;提交的申请信息都是由运营商…...

JavaWeb 22.Node.js_简介和安装

有时候&#xff0c;后退原来是向前 —— 24.10.7 一、什么是Node.js Node.js 是一个于 Chrome V8 的 JavaScript 运行时环境&#xff0c;可以使 JavaScript 运行在服务器端。使用 Node.js&#xff0c;可以方便地开发服务器端应用程序&#xff0c;如 Web 应用、API、后端服务&a…...

APIJSON的使用

APIJSON是一个用于简化后端接口开发的工具&#xff0c;在Java中可以按照以下步骤使用&#xff1a; 1. 引入依赖 在Java项目中&#xff0c;需要引入APIJSON的相关依赖。如果使用Maven&#xff0c;可以在pom.xml文件中添加以下依赖&#xff1a; <dependency><groupId…...

简单三步完成 Telegram 生态的 Web3 冷启动

在竞争激烈的 Web3 领域&#xff0c;强有力的启动往往能决定成败。Telegram 无疑当下最火热的流量池&#xff0c;是很多 Web3 项目冷启动阶段的必选项。 但眼看着好多项目在 Telegram 生态火速获取百万级甚至千万级别的用户&#xff0c;自己的项目要怎么开始做增长&#xff0c;…...

Go Wails 学习笔记:创建第一个项目

文章目录 1. 安装 Wails2. 创建 Wails 项目3. 项目结构4. 运行项目5. 构建项目6. 部署和发布总结 Wails 是一个用于构建跨平台桌面应用程序的框架&#xff0c;允许开发者使用前端技术&#xff08;如 HTML、CSS、JavaScript&#xff09;以及 Go 语言来开发桌面应用。本文基于官方…...

Postman使用-基础篇

前言 本教程将结合业界广为推崇和使用的RestAPI设计典范Github API&#xff0c;详细介绍Postman接口测试工具的使用方法和实战技巧。 在开始这个教程之前&#xff0c;先聊一下为什么接口测试在现软件行业如此重要&#xff1f; 为什么我们要学习Postman&#xff1f; 现代软件…...

LeetCode 202.快乐数

LeetCode 202.快乐数 C 思路&#xff1a; 用快慢指针来进行解答&#xff0c;可以将其看做一个回环链表&#xff0c;慢指针完成一次平方和操作&#xff0c;快指针完成两次平方和操作&#xff0c;当快慢指针相遇时&#xff0c;判断快慢指针是否为1(为1以后无论怎么取平方和都会为…...

Redis-03 持久化(RDB, AOF,混合持久化)及原理

1&#xff0c;持久化 Redis的持久化是必须的&#xff0c;当Redis服务宕机后&#xff0c;如果没有持久化&#xff0c;重启服务后redis中的数据都将丢失&#xff0c;所有的数据操作都将直连数据库&#xff0c;系统性能会大幅降低&#xff0c;所以在使用Redis做缓存服务时必须持久…...

TikTok账号策略:IP和网络环境的要求分析

在当今社交媒体迅猛发展的时代&#xff0c;TikTok作为一款短视频平台&#xff0c;凭借其独特的算法和庞大的用户基础&#xff0c;吸引了越来越多的内容创作者和营销人员。成功地运营一个TikTok账号&#xff0c;除了优质的内容创作外&#xff0c;良好的IP和网络环境也至关重要。…...

vue后台管理系统从0到1(5)

文章目录 vue后台管理系统从0到1&#xff08;5&#xff09;完善侧边栏修改bug渲染header导航栏 vue后台管理系统从0到1&#xff08;5&#xff09; 接上一期&#xff0c;我们需要完善我们的侧边狼 完善侧边栏 我们在 element 组件中可以看见&#xff0c;这一个侧边栏是符合我们…...

OpenAI的新功能Canvas,效果还不错

时隔两年&#xff0c;ChatGPT终迎来界面全新升级&#xff01; 这一次&#xff0c;OpenAI官宣推出类似 Anthropic 的 Artifacts 的界面交互功能 canvas&#xff0c;并称这是一种使用 ChatGPT 写作和编程的新方式。不论是写作&#xff0c;还是编码&#xff0c;都可以开启全新的交…...

了解一些常用的Javascript对象方法

javascript 的对象包含许多有用的方法&#xff0c;可以帮助开发人员轻松操作对象。让我们通过简短的解释和示例来了解一些最重要的内容 object.create()object.assign()object.keys()object.values()object.entries()object.freeze()object.seal()object.preventextensions()o…...

【知识科普】GraphQL一个强大的API查询语言

文章目录 概述&#x1f4da; GraphQL 的类型系统是如何工作的&#xff1f;&#x1f50d; 能否举例说明 GraphQL 的类型系统在实际应用中是如何工作的&#xff1f;位置步骤 1: 定义类型步骤 2: 实现解析器步骤 3: 客户端查询步骤 4: 执行查询 &#x1f6e0;️ 在实际开发中&…...

Spring Boot 整合达梦

Maven 依赖 <dependency><groupId>com.dameng</groupId><artifactId>DmJdbcDriver18</artifactId><version>8.1.2.192</version></dependency> yml配置 datasource:master:url: jdbc:dm://192.168.211.113:30236username: WE…...

Vue.js 组件开发基本步骤

Vue.js 是一个构建用户界面的渐进式框架&#xff0c;它被设计为能够轻松地被集成进项目的部分功能&#xff0c;或者用于构建完整的前端应用。组件化是 Vue.js 的核心概念之一&#xff0c;它允许开发者将界面拆分成独立、可复用的组件&#xff0c;每个组件负责应用中的一小部分功…...

博客搭建之路:hexo使用next主题渲染流程图

文章目录 hexo使用next主题渲染流程图 hexo使用next主题渲染流程图 hexo版本5.0.2 npm版本6.14.7 next版本7.8.0 next主题的配置文件中搜索找到mermaid&#xff0c;把enable配置改为true mermaid:enable: true# Available themes: default | dark | forest | neutraltheme: de…...

【数据结构与算法】线性表顺序存储结构

文章目录 一.顺序表的存储结构定义1.1定义1.2 图示1.3结构代码*C语言的内存动态分配 二.顺序表基本运算*参数传递2.1建立2.2初始化(InitList(&L))2.3销毁(DestroyList(&L))2.4判断线性表是否为空表(ListEmpty(L))2.5求线性表的长度(ListLength(L))2.6输出线性表(DispLi…...

Unix Standardization and Implementations

Unix标准化 在Unix未制定较为完备的标准时&#xff0c;各个平台的系统调用方式各异&#xff0c;所开发出的应用程序存在可移植性差的特点&#xff0c;因此人们呼吁指定一套Unix标准来规范接口&#xff0c;增加应用程序的可移植性。所谓Unix标准即适用于Unix环境下的一系列函数…...

Windows 与 Java 环境下的 Redis 利用分析

1 前言 在最近的一次攻防演练中&#xff0c;遇到了两个未授权访问的 Redis 实例。起初以为可以直接利用&#xff0c;但后来发现竟然是Windows Java (Tomcat)。因为网上没有看到相关的利用文章&#xff0c;所以在经过摸索&#xff0c;成功解决之后决定简单写一写。 本文介绍了…...

机器视觉系统硬件组成之工业相机篇

工业相机是一种非常重要的机器视觉器件&#xff0c;它能够将被采集的图像信息通过电路转换成电信号&#xff0c;再通过模数转换器&#xff08;ADC&#xff09;将其转化为数字信号&#xff0c;最后以标准的视频信号输出。工业相机在机器视觉领域得到了广泛应用&#xff0c;包括质…...

离线安装bitnami-gitlab8.8.4+汉化

注意&#xff1a; 常规安装gitlab需要联网&#xff0c;而按装bitnami-gitlab无需联网(bitnami-gitlab用于内网环境无法联网时安装gitlab&#xff0c;两者是一个东西只是名字不一样)bitnami-gitlab-8.8.4版本可以汉化成功新用户注册账户无需激活也可以直接登录&#xff0c;因为…...