在企业级应用中,文档预览不仅仅是"能看",更是关于隐私安全(不传三方服务器 )与 极致性能(大文件不卡顿)的博弈。
今天我们就从实战角度,手把手拆解如何利用 docx-preview 和 vue-pdf-embed 搭建一套纯前端、工业级的文档预览系统。
一、 通俗易懂:它们到底是怎么工作的?
我们可以把文档预览想象成"翻译"过程:
- docx-preview:它像是一个**"拆解大师"**。Word 文档(.docx)本质上是一个压缩包,里面装满了 XML 格式的文字和排版信息。这个库在浏览器里直接解压它,并把 XML 翻译成我们熟悉的 HTML 网页。
- vue-pdf-embed :它像是一个**"高清投影仪"**。基于强大的
pdf.js,它将 PDF 的每一页绘制在 Canvas(画布)上,并额外覆盖一层透明的"文字层",让你可以像在网页上一样选中和复制文字。
二、 Word 预览篇:docx-preview 极速落地
在金融场景下,Word 预览最怕样式乱掉。使用这个库时,必须注意样式隔离。
1. 实战代码:封装一个稳健的 Word 预览组件
代码段
xml
<template>
<div class="word-preview-container">
<div v-if="loading" class="status-tip">文档解析中...</div>
<div ref="fileContainer" class="render-box"></div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import { renderAsync } from 'docx-preview';
const props = defineProps({ url: { type: String, required: true } });
const fileContainer = ref(null);
const loading = ref(false);
const getFileAndRender = async () => {
loading.value = true;
try {
// 1. 获取二进制流
const response = await fetch(props.url);
const blob = await response.blob();
// 2. 渲染
await renderAsync(blob, fileContainer.value, null, {
className: "docx-inner", // 自定义类名
inWrapper: true, // 必须开启,确保样式被包裹在内部,不污染全局
ignoreWidth: false, // 尊重原文档宽度
});
} catch (e) {
console.error('Word 预览失败', e);
} finally {
loading.value = false;
}
};
onMounted(() => getFileAndRender());
</script>
<style scoped>
.render-box {
width: 100%;
height: 80vh;
overflow-y: auto;
/* 解决 8 年老兵最头疼的:居中显示与背景色 */
background-color: #f0f2f5;
padding: 20px;
}
</style>
三、 PDF 预览篇:vue-pdf-embed 的深度掌控
在处理金融合规文档或长篇研报时,单纯展示图片是不够的。你需要**文字层(Text Layer)**来搜索和复制。
1. 实战代码:带"文字层"的高保真预览
代码段
xml
<template>
<div class="pdf-preview-box">
<VuePdfEmbed
:source="props.url"
text-layer
annotation-layer
class="pdf-canvas"
/>
</div>
</template>
<script setup>
import VuePdfEmbed from 'vue-pdf-embed'
// 必须引入样式,否则文字层会错位
import 'vue-pdf-embed/dist/styles/textLayer.css'
import 'vue-pdf-embed/dist/styles/annotationLayer.css'
const props = defineProps({ url: { type: String, required: true } })
</script>
<style scoped>
.pdf-preview-box {
width: 100%;
height: 80vh;
overflow-y: auto;
}
/* 优化 Canvas 渲染,防止高分屏模糊 */
.pdf-canvas {
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
margin-bottom: 20px;
}
</style>
四、"性能避坑"指南
- 内存回收 :这两个库在渲染大文件时会占用极高内存。在 Vue 组件卸载(
onUnmounted)时,务必清空容器内容(fileContainer.value.innerHTML = ''),否则多看几个文档浏览器就 OOM 了。 - 异步切断 :如果用户点击列表过快,前一个文档还没加载完就换下一个,记得使用
AbortController取消之前的fetch请求。 - 样式冲突 :
docx-preview会插入大量 CSS。一定要开启inWrapper: true配置,否则你会发现你的导航栏背景色莫名其妙被 Word 的背景色覆盖了。