更新记录
0.2.16(2026-08-10)
- 修复:普通 uni-app Vue2/Vue3 Android App 的 RenderJS 无法通过
this.$el 稳定找到 PDF iframe,导致 goToPage() 调用后没有跳页
- 修复:
getCurrentPageIndex() 和 getTotalPages() 在同一 Android App 通信路径下可能无响应的问题
- 兼容:为每个 PDF iframe 绑定 viewer 实例唯一 ID,RenderJS 从视图层
document 精确定位,避免多组件串台
0.2.15(2026-08-10)
- 修复:普通 uni-app Vue2/Vue3 Android App 调用
goToPage() 后没有跳页的问题
- 修复:App 逻辑层不再直接访问 RenderJS 层 iframe,页码控制与查询指令统一由 RenderJS 转发给 PDF.js
- 修复:App 的
load 事件改为等待 PDF 文档实际解析完成,支持在 @load 回调中立即调用 goToPage()
- 兼容:H5 原有 iframe 通信方式保持不变,
getCurrentPageIndex() 和 getTotalPages() 同步适配 Android App 桥接
0.2.14(2026-07-28)
- 修复:uni-app x Web 端不再导入仅 App 原生平台提供的
ViewPdfNative,解决 does not provide an export named 'ViewPdfNative'
- 兼容:uni-app x Web 端改用动态 iframe 加载内置 PDF.js,保留
load、error、pageChange、lastPage 事件
- 兼容:Web 端继续支持
goToPage、prevPage、nextPage、getCurrentPageIndex 和 getTotalPages
- 修复:切换 PDF 地址或参数后清空旧 iframe 消息去重记录,避免新一轮
load / error 事件被误判为重复消息
查看更多
平台兼容性
uni-app(5.0)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
√ |
√ |
√ |
- |
5.0 |
12 |
- |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| - |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
uni-app x(5.0)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| √ |
√ |
5.0 |
12 |
- |
- |
其他
view-pdf PDF 查看器
view-pdf 同时支持普通 uni-app Vue2/Vue3 和 uni-app x。普通 uni-app 在 H5/App 使用内置 PDF.js,uni-app x App 使用 UTS 原生组件。
特性
- Vue2 和 Vue3 共用同一个组件
- App/H5 页面内直接查看,不弹出系统下载
- PDF.js 3.11.174 和 worker 已内置
- 内置 169 个中文 CMap 资源
- 支持
paged 分页和 scroll 连续滚动
- 翻页或滚动到 PDF 末尾时触发
@lastPage,由业务自定义提示
- 支持
quality 和 zoom
- 普通 uni-app Vue2/Vue3 无需自定义调试基座
- uni-app x App 支持 Android
PdfRenderer 和 iOS PDFKit
平台
| 平台 |
支持 |
说明 |
| uni-app Vue2 H5 |
✅ |
内置 PDF.js |
| uni-app Vue2 App |
✅ |
内置 PDF.js |
| uni-app Vue3 H5 |
✅ |
内置 PDF.js |
| uni-app Vue3 App |
✅ |
内置 PDF.js |
| uni-app x App-Android |
✅ |
UTS 原生 PdfRenderer |
| uni-app x App-iOS |
✅ |
UTS 原生 PDFKit |
| 小程序 |
❌ |
暂不支持 |
Vue3 Demo
<template>
<view class="page">
<button size="mini" @click="reloadPdf">重新加载</button>
<text>{{ statusText }}</text>
<PdfViewer
v-if="pdfUrl"
class="viewer"
:url="pdfUrl"
:quality="2"
:zoom="1"
mode="paged"
@load="onPdfLoad"
@error="onPdfError"
/>
</view>
</template>
<script setup>
import { nextTick, ref } from 'vue'
import PdfViewer from '@/uni_modules/view-pdf/components/view-pdf/view-pdf.vue'
const SAMPLE_PDF = 'https://raw.githubusercontent.com/mozilla/pdf.js/master/test/pdfs/basicapi.pdf'
const pdfUrl = ref('')
const statusText = ref('正在准备 PDF')
const loadPdf = async () => {
pdfUrl.value = ''
statusText.value = '正在加载 PDF'
await nextTick()
pdfUrl.value = SAMPLE_PDF
}
const reloadPdf = () => loadPdf()
const onPdfLoad = () => { statusText.value = 'PDF 加载成功' }
const onPdfError = (e) => { statusText.value = e?.errMsg || 'PDF 加载失败' }
loadPdf()
</script>
<style>
.page { height: 100vh; display: flex; flex-direction: column; }
.viewer { flex: 1; min-height: 400px; }
</style>
Vue2 Demo
<template>
<view class="page">
<button size="mini" @click="reloadPdf">重新加载</button>
<text>{{ statusText }}</text>
<PdfViewer
v-if="pdfUrl"
class="viewer"
:url="pdfUrl"
:quality="2"
:zoom="1"
mode="paged"
@load="onPdfLoad"
@error="onPdfError"
></PdfViewer>
</view>
</template>
<script>
import PdfViewer from '@/uni_modules/view-pdf/components/view-pdf/view-pdf.vue'
const SAMPLE_PDF = 'https://raw.githubusercontent.com/mozilla/pdf.js/master/test/pdfs/basicapi.pdf'
export default {
components: { PdfViewer },
data() {
return { pdfUrl: '', statusText: '正在准备 PDF' }
},
onLoad() {
this.loadPdf()
},
methods: {
loadPdf() {
this.pdfUrl = ''
this.statusText = '正在加载 PDF'
this.$nextTick(() => { this.pdfUrl = SAMPLE_PDF })
},
reloadPdf() {
this.loadPdf()
},
onPdfLoad() {
this.statusText = 'PDF 加载成功'
},
onPdfError(e) {
this.statusText = e && e.errMsg ? e.errMsg : 'PDF 加载失败'
}
}
}
</script>
<style>
.page { height: 100vh; display: flex; flex-direction: column; }
.viewer { flex: 1; min-height: 400px; }
</style>
uni-app x Demo(.uvue)
uni-app x 不能直接复制普通 .vue Demo。App 端请先下载网络 PDF,再把 tempFilePath 传给原生组件。
<template>
<view class="page">
<button :disabled="downloading" @click="loadPdf">下载并加载</button>
<text>{{ statusText }}</text>
<view class="viewer-shell">
<view-pdf
v-if="pdfPath.length > 0"
class="viewer"
:url="pdfPath"
:quality="2"
:zoom="1"
mode="paged"
@load="onPdfLoad"
@error="onPdfError"
></view-pdf>
</view>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const SAMPLE_PDF = 'https://raw.githubusercontent.com/mozilla/pdf.js/master/test/pdfs/basicapi.pdf'
const pdfPath = ref('')
const statusText = ref('等待下载')
const downloading = ref(false)
const loadPdf = () : void => {
if (downloading.value) return
downloading.value = true
pdfPath.value = ''
statusText.value = '正在下载 PDF'
uni.downloadFile({
url: SAMPLE_PDF,
success: (result) => {
if (result.statusCode == 200 && result.tempFilePath.length > 0) {
pdfPath.value = result.tempFilePath
statusText.value = '下载完成,正在渲染'
return
}
statusText.value = 'PDF 下载失败:HTTP ' + result.statusCode.toString()
},
fail: (error) => {
statusText.value = error.errMsg.length > 0 ? error.errMsg : 'PDF 下载失败'
},
complete: (_result) => {
downloading.value = false
}
})
}
const onPdfLoad = (_event : any) : void => {
statusText.value = 'PDF 加载成功'
}
const onPdfError = (_event : any) : void => {
statusText.value = 'PDF 加载失败,请检查路径或自定义基座'
}
loadPdf()
</script>
<style>
.page { flex: 1; flex-direction: column; }
.viewer-shell, .viewer { flex: 1; }
</style>
uni-app x App 使用 UTS 原生能力,真机运行时需制作自定义调试基座。
Props
| 属性 |
类型 |
默认值 |
说明 |
url |
String |
'' |
普通 uni-app 传 HTTP/HTTPS;uni-app x App 传下载后的本地路径 |
quality |
Number |
2 |
渲染清晰度 1-4,只改变像素精度,不改变显示尺寸 |
zoom |
Number |
1 |
可见缩放 0.5-4;1 为适应容器宽度,2 为两倍宽度 |
mode |
String |
paged |
paged 只显示当前页,scroll 连续渲染 |
Events
| 事件 |
说明 |
load |
viewer 加载成功 |
error |
viewer 或 PDF 加载失败 |
pageChange |
当前页变化,返回从 0 开始的 currentPage 和 totalPages |
lastPage |
分页进入末页或连续滚动到底时触发,返回 currentPage 和 totalPages |
注意
- 普通 uni-app App 请传入可访问的 HTTP/HTTPS PDF URL,不需要先调用
uni.downloadFile。
- PDF 服务器需允许 CORS,否则 PDF.js 无法读取文件。
- 建议使用显式
import PdfViewer 的方式,避免与其他同名组件冲突。
- uni-app x
.uvue 页面直接使用 easycom <view-pdf>,不要显式导入普通 .vue 组件。