需求: 在h5端预览pdf,同时需要判断pdf已经看完,要保存pdf的当前页面,下次打开的时候要回到当前页
方式:vue-pdf与pdf.js+iframe
pdf.js + iframe
由于我的项目是要在企业微信打开,所以必须要打包到服务器上测试:所以,我的pdf文件需要先放到服务器上面。在官网上下载pdf.js,不同版本可能有不同的坑,如果想深入了解或者想改pdf.js源码来实现自己的需求,就还是老老实实看源码。
//我是直接用Pdf.js已有的一个显示页面来预览,功能很齐全,但是会感觉比较复杂,功能太多,有很多是需求用不上的。
<iframe id="iframe_id" ref="pdf" src="服务器地址/generic/web/viewer.html" width="100%" height="600" />
如果在单页面应用中,一个页面只是要预览一个pdf(既只传一个src给pdf.js)那用pdf.js插件还是不错的,显示也挺美观.
如果要拿当前页面,我们可以通过
//拿到当前页码
this.$refs['pdf'].contentWindow.PDFViewerApplication.page
//拿到pdf总页数
this.$refs['pdf'].contentWindow.PDFViewerApplication.pagesCount
但是如果在单页面应用中,你有可能需要在同一个页面打开几个不同的pdf,传不同的src.就会出现一个问题:
当你需要回退的时候,你回退的页面是你上一次请求的pdf的页面:
如:我在/#/onlineClass页面跳转进入/#/onlineClassDetail,然后在该页面用iframe打开第一个pdf,然后我点击一个按钮,打开了第二个pdf.然后又打开第三个pdf文件.这时候我回退,我正常的需求是回退到上一个页面(既:/#/onlineClass),但是实际上,是会回退到请求第二个pdf,页面还是在/#/onlineClassDetail.
最后就是因为这个问题,我放弃了pdf.js
vue-pdf
直接npm下载
npm install --save vue-pdf
import pdf from 'vue-pdf'
//引入
export default {
name: 'Demo',
components: {
pdf
},
<div @click="changePdfRotate">
<pdf
:class="{pdfH:pdfRotate !== 0}"
:src="pdfFileSrc"
:page="currentPage"
:rotate="pdfRotate"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
/>
</div>
//这里是配上了上一页与下一页按钮
<div v-if="!showViewPdf">
<p class="arrow">
<span class="m-btnn " :class="{grey: currentPage==1,trans:pdfRotate !== 0 }" @click="changePdfPage(0)">上一页</span>
<span class="page" :class="{trans:pdfRotate !== 0}">{{ currentPage }} / {{ pageCount }}</span>
<span class="m-btnn fr" :class="{grey: currentPage==pageCount,trans:pdfRotate !== 0}" @click="changePdfPage(1)">下一页</span>
</p>
</div>
// pdf加载时
loadPdfHandler(e) {
this.showViewPdf = false
this.$refs['pdfBox'].className = 'pdf'
},
总结:
vue-pdf,不需要用iframe,就会少了很多iframe的坑,直接用canvas渲染出来,
iframe还会有一个浏览器的嵌入页面保护机制,不是同源的资源是无法在iframe中显示的.有一个 X-Frame-Options 的请求头.(可以自行百度一下)
但是相对于pdf.js,可能的确显示页面没有写pdf.js这个两位大佬写的漂亮.
但是如果要做一些类似课堂类型显示pdf文件的需求,pdf.js略显臃肿,因为很多功能都不需要用到.
但是如果自己直接跳转页面打开pdf预览.那么pdf.js是一个很好的选择.