file-preview-vue2-1
v1.0.0
Published
Vue 2 file preview component (txt / docx / pdf / pptx) with keyword highlight
Readme
FilePreview 文件预览组件(Vue 2)
基于 Vue 2(建议 2.7.x,以使用 Composition API)的文件预览组件,支持多种文件格式的在线预览,包括文本文件、Word 文档、PDF 文件和 PowerPoint 演示文稿。
功能特性
- 📄 多格式支持:自动识别并预览 TXT、DOC/DOCX、PDF、PPT/PPTX 等文件格式
- 🔍 文本高亮:支持关键词高亮显示,可自定义高亮样式
- 📑 分页导航:支持 PDF 和 PPT 文件的页码跳转和定位
- ⚡ 性能优化:大文件下载时显示实时下载速度,提供加载状态反馈
- 🎨 响应式设计:可根据容器宽度更新内部布局(见
triggerFullFill) - ⚠️ 错误处理:完善的错误处理机制,文件加载失败时显示友好提示
支持的文件格式
| 文件类型 | 扩展名 | 说明 |
|---------|--------|------|
| 文本文件 | .txt | 纯文本文件预览 |
| Word 文档 | .doc, .docx | 使用 docx-preview 渲染 |
| PDF 文件 | .pdf | 使用 vue-pdf-embed(Vue 2 构建入口)渲染 |
| PowerPoint | .ppt, .pptx | 使用 pptx-preview 渲染 |
环境要求
- Vue:
^2.7.0(推荐 2.7.16) - Element UI:
^2.15.x(组件内使用Loading,需在工程中Vue.use(ElementUI)) - 构建工具需能编译
.vue与 Less(如 Webpack +vue-loader+less-loader,或 Vite +vite-plugin-vue2)
安装依赖
方式一:使用发布的 npm 包(.tgz)
在 file-preview 目录执行 npm pack(或 npm run pack),会生成形如 core-pilot-file-preview-vue2-<version>.tgz 的文件(<version> 与当前 package.json 中一致),在业务项目中安装:
npm install ./path/to/core-pilot-file-preview-vue2-1.0.0.tgz包名:@core-pilot/file-preview-vue2。package.json 的 main 为 index.vue(源码包,非预编译 dist)。
若打包工具无法通过包名解析到 .vue,可改为显式路径:
import FilePreview from '@core-pilot/file-preview-vue2/index.vue';方式二:拷贝源码
将组件目录拷入工程(如 src/components/file-preview),自行保证依赖一致。
Peer 依赖(建议在业务项目中安装)
安装 .tgz 时,npm 会按子包 package.json 的 dependencies 一并安装传递依赖;为避免多份 vue、并便于锁定版本,业务侧仍建议显式安装:
npm install vue@^2.7 element-ui docx-preview vue-pdf-embed pptx-preview mark.js lodashdocx-preview / vue-pdf-embed 还会用到 jszip、pdfjs-dist 等,一般由上述包自动带上;若构建报缺模块,再手动安装即可。
PDF 子组件固定从
vue-pdf-embed/dist/vue2-pdf-embed.js引入。请安装仍提供该文件的vue-pdf-embed版本;独立子包@core-pilot/file-preview-vue2的package.json声明为^1.2.1。若在 monorepo 中被解析到更高主版本,以实际包内是否包含上述路径为准。
全局注册 Element UI(必须)
组件依赖 Element UI 的 Loading,请在入口中:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);样式:index.vue 已引入 ./style/index.less,请确保构建链能处理 Less。
基础用法
以下示例使用 Vue 2.7 的 setup + defineComponent(与 Vue 3 写法接近)。若项目为纯 Options API,见下文「Options API 示例」。
<template>
<file-preview
:url="fileUrl"
:highlight="keywords"
:page="currentPage"
:show-highlight="true"
/>
</template>
<script>
import { defineComponent, ref } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
name: 'DemoPage',
components: {
FilePreview,
},
setup() {
const fileUrl = ref('https://example.com/document.pdf');
const keywords = ref(['关键词1', '关键词2']);
const currentPage = ref(1);
return {
fileUrl,
keywords,
currentPage,
};
},
});
</script>本地路径引入示例:
import FilePreview from '@/components/file-preview/index.vue';API
Props
| 参数 | 说明 | 类型 | 默认值 | 必填 |
|------|------|------|--------|------|
| url | 文件资源的 URL 地址 | string | '' | 是 |
| highlight | 需要高亮的关键词数组 | string[] | [] | 否 |
| page | 当前页码(PDF/PPT 有效) | number | 1 | 否 |
| showHighlight | 是否显示高亮 | boolean | true | 否 |
模板中推荐使用 kebab-case::show-highlight、@close-loading 等。
Methods
通过 ref 取得子组件实例后,可调用:
| 方法名 | 说明 | 参数 | 返回值 |
|--------|------|------|--------|
| triggerFullFill | 用当前根节点 clientWidth 更新内部宽度(用于 PDF/PPT 随容器变宽重排);不调用浏览器全屏 API | - | void |
| repositioning | 跳转到指定页(仅 PDF / PPT 有效;TXT/DOC 无操作) | page?: number, smooth?: boolean | void |
Vue 2.7(setup + ref):
const previewRef = ref(null);
// 调用:previewRef.value && previewRef.value.repositioning(5, true);Options API:
this.$refs.previewRef.repositioning(5, true);使用示例
基础预览
<template>
<file-preview :url="'https://example.com/document.pdf'" />
</template>
<script>
import { defineComponent } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
components: { FilePreview },
});
</script>带关键词高亮
<template>
<file-preview
:url="fileUrl"
:highlight="['重要', '注意', '关键']"
:show-highlight="true"
/>
</template>
<script>
import { defineComponent, ref } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
components: { FilePreview },
setup() {
const fileUrl = ref('https://example.com/document.pdf');
return { fileUrl };
},
});
</script>PDF 页码跳转
<template>
<div>
<button type="button" @click="jumpToPage(5)">跳转到第 5 页</button>
<file-preview
ref="previewRef"
:url="pdfUrl"
:page="currentPage"
/>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
components: { FilePreview },
setup() {
const previewRef = ref(null);
const pdfUrl = ref('https://example.com/document.pdf');
const currentPage = ref(1);
const jumpToPage = (page) => {
currentPage.value = page;
if (previewRef.value) {
previewRef.value.repositioning(page, true);
}
};
return {
previewRef,
pdfUrl,
currentPage,
jumpToPage,
};
},
});
</script>动态切换文件
<template>
<div>
<button type="button" @click="switchFile">切换文件</button>
<file-preview
:url="currentFileUrl"
:highlight="keywords"
/>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
components: { FilePreview },
setup() {
const currentFileUrl = ref('https://example.com/file1.pdf');
const keywords = ref(['关键词']);
const switchFile = () => {
currentFileUrl.value = 'https://example.com/file2.docx';
};
return {
currentFileUrl,
keywords,
switchFile,
};
},
});
</script>容器变宽后重算布局(triggerFullFill)
在浏览器全屏、侧栏收起等导致预览区域宽度变化后,可调用 triggerFullFill(),用新的容器宽度刷新 PDF/PPT 的展示(与是否进入系统全屏无关,名称沿用历史接口)。
<template>
<div>
<button type="button" @click="relayout">容器变宽后重算</button>
<file-preview
ref="previewRef"
:url="fileUrl"
/>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
import FilePreview from '@core-pilot/file-preview-vue2';
export default defineComponent({
components: { FilePreview },
setup() {
const previewRef = ref(null);
const fileUrl = ref('https://example.com/document.pdf');
const relayout = () => {
if (previewRef.value) {
previewRef.value.triggerFullFill();
}
};
return {
previewRef,
fileUrl,
relayout,
};
},
});
</script>Options API 示例(不使用 setup)
<template>
<div>
<file-preview
ref="previewRef"
:url="fileUrl"
:highlight="keywords"
:page="currentPage"
:show-highlight="true"
/>
</div>
</template>
<script>
import FilePreview from '@core-pilot/file-preview-vue2';
export default {
components: {
FilePreview,
},
data() {
return {
fileUrl: 'https://example.com/document.pdf',
keywords: ['关键词1', '关键词2'],
currentPage: 1,
};
},
methods: {
jumpToPage(page) {
this.currentPage = page;
this.$refs.previewRef.repositioning(page, true);
},
},
};
</script>组件内部实现
文件类型识别
组件会根据 URL 的文件扩展名自动识别文件类型:
.doc,.docx→ Word 文档预览.pdf→ PDF 预览.ppt,.pptx→ PowerPoint 预览- 其他 → 文本文件预览
子组件说明
- TextPreview:处理纯文本文件
- DocPreview:使用
docx-preview渲染 Word - PdfPreview:使用
vue-pdf-embed的 Vue 2 入口渲染 PDF - PptPreview:使用
pptx-preview渲染 PPT
逻辑模块(hooks,实为组合函数)
useHighlight
文本高亮,基于 mark.js(源码为 hooks/useHighlight.js)。
useRender
下载与 Loading 文案相关:downloadWithSpeed、updateDownloadFinish、tipsVNode 等。
样式定制
组件使用 Less,主要类名包括:
.filePreview:主容器.fileContainer:单类型预览外层.file-error:错误提示.text-render、.doc-render、.pdf-render、.ppt-render:各类型内容区
可在业务侧覆盖上述类名。
注意事项
- 跨域:文件 URL 需可访问,并按需配置 CORS
- 浏览器:建议使用现代浏览器;PDF 能力依赖
vue-pdf-embed/ pdf.js - 性能:频繁切换 URL 或页码时,内部已做部分防抖与监听优化
- 与 Vue 3 技术栈差异:本组件实现为 Vue 2 + Element UI;若你手头仍是 Vue 3 + Element Plus 的旧版
@core-pilot/client-vue文档或产物,请勿与当前 Vue 2 版FilePreview混在同一应用入口。本仓库当前分支若已将client-vue切到 Vue 2,则包内导出的FilePreview即本组件,与独立.tgz二选一即可。
错误处理
加载失败时展示「文件打开失败」。常见原因:
- URL 无效或网络不可达
- 跨域被拒绝
- 格式不支持或服务器错误
开发说明
目录结构
file-preview/
├── index.vue # 主组件
├── LocalDebugDemo.vue # 本地调试壳层(Vite / Storybook 共用)
├── textPreview.vue
├── docPreview.vue
├── pdfPreview.vue
├── pptPreview.vue
├── hooks/
│ ├── useHighlight.js
│ └── useRender.js
├── extensions/
│ └── highlight.js
├── style/
│ └── index.less
└── stories/ # Storybook 示例(不随 npm pack 发布)扩展新格式
- 在
index.vue中增加类型分支 - 新增对应
xxxPreview.vue - 在模板中挂载子组件
License
MIT
