安装:

这个没有啥背景知识可讲,我们直接跳到安装环节,vue-pdf 和其他vue组件的安装并无不同,打开命令行,敲入:
npm install --save vue-pdf
注意路径。别在桌面调出来个终端安装了,这种直接打回去重学Vue。

vue-pdf 初体验:

安装完之后,使用vue-pdf非常简单,和其他的组件并没有什么不同,上代码:
首先我们需要引入这个组件:

  1. import pdf from 'vue-pdf'
  2. export default {
  3. components:{
  4. pdf
  5. },
  6. data(){
  7. return {
  8. url:"http://stora/PDF/PlayerAPI_v1.0.6.pdf",
  9. }
  10. }

然后在页面使用vue-pdf,只需要添加标签:

重启你的项目,访问这个界面,你大概率会发现pdf已经成功显示在你的界面上了。这没有任何问题,但是,正当你准备拿起一根烟,点上,伴着舒适的《美丽的梭罗河》,欣赏你成功的杰作的时候,你会发现,我擦,为啥只有一页,当玻璃杯碰在一起,满世界都是梦破碎的声音。
所以,这只是初体验,如果你的pdf只有一页,这样写当然没什么问题,但是当我们呢pdf 有很多页的时候,你会发现,这行不通了。所以,接下来,我们来看看怎么让它显示多页。

vue-pdf 渐入佳境:

其实,想要显示多页也没那么复杂,你每次就显示一页,我,直接v-for 循环,直接显示完,简单粗暴。
页面代码:

  1. <template>
  2. <div>
  3. <pdf v-for="i in numPages" :key="i" :src="url" :page="i"></pdf>
  4. </div>
  5. </template>
  6. <script>
  7. import pdf from 'vue-pdf'
  8. export default {
  9. components: {
  10. pdf
  11. },
  12. data(){
  13. return{
  14. url: '',
  15. numPages:1,
  16. }
  17. },
  18. mounted: function() {
  19. this.getNumPages("http://storage.xuetaF/PlayerAPI_v1.0.6.pdf")
  20. },
  21. methods: {
  22. getNumPages(url) {
  23. var loadingTask = pdf.createLoadingTask(url)
  24. loadingTask.then(pdf => {
  25. this.url = loadingTask
  26. this.numPages = pdf.numPages
  27. }).catch((err) => {
  28. console.error('pdf加载失败')
  29. })
  30. },
  31. }
  32. }
  33. </script>

各个属性:

  • url :pdf 文件的路径,可以是本地路径,也可以是在线路径。
  • numPages : pdf 文件总页数。

getNumPages 计算总页数,顺便给url和numPages赋值。
唯一需要大家注意的是这句:
this.getNumPages(“http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf“)

注意啊,这句不一定非要写到mounted里面,你想写哪就写哪,比如你前端请求后端,后端返回一个pdf 的url,在那里写就行,写在你需要的地方。

vue-pdf 轻车熟路:

很多人看到这,就这,就这?万一,我pdf有一千页,我浏览器还不得裂开,我追求的是那种在微醺的下午,一页一页的翻看的感觉,你能给我吗?
我不能,才怪,保证满足你。

接下来,我们一一介绍这些都是个啥。
参数介绍:

  • page: 当前显示的页数,比如第一页page=1
  • rotate : 旋转角度,比如0就是不旋转,+90,-90 就是水平旋转。
  • progress :当前页面的加载进度,范围是0-1 ,等于1的时候代表当前页已经完全加载完成了。
  • page-loaded :页面加载成功的回调函数,不咋能用到。
  • num-pages :总页数
  • error :加载错误的回调
  • link-clicked:单机pdf内的链接会触发。

其他:

  • print 这个是打印函数。 注意:谷歌浏览器会出现乱码,这个和字体有关系。

来,js代码走一个:

  1. <template>
  2. <div>
  3. <div class="tools">
  4. <bk-button :theme="'default'" type="submit" :title="'基础按钮'" @click.stop="prePage" class="mr10"> 上一页</bk-button>
  5. <bk-button :theme="'default'" type="submit" :title="'基础按钮'" @click.stop="nextPage" class="mr10"> 下一页</bk-button>
  6. <div class="page">{{pageNum}}/{{pageTotalNum}} </div>
  7. <bk-button :theme="'default'" type="submit" :title="'基础按钮'" @click.stop="clock" class="mr10"> 顺时针</bk-button>
  8. <bk-button :theme="'default'" type="submit" :title="'基础按钮'" @click.stop="counterClock" class="mr10"> 逆时针</bk-button>
  9. </div>
  10. <pdf ref="pdf"
  11. :src="url"
  12. :page="pageNum"
  13. :rotate="pageRotate"
  14. @progress="loadedRatio = $event"
  15. @page-loaded="pageLoaded($event)"
  16. @num-pages="pageTotalNum=$event"
  17. @error="pdfError($event)"
  18. @link-clicked="page = $event">
  19. </pdf>
  20. </div>
  21. </template>
  • page: 当前显示的页数,比如第一页page=1
  • rotate : 旋转角度,比如0就是不旋转,+90,-90 就是水平旋转。
  • progress :当前页面的加载进度,范围是0-1 ,等于1的时候代表当前页已经完全加载完成了。
  • page-loaded :页面加载成功的回调函数,不咋能用到。
  • num-pages :总页数
  • error :加载错误的回调
  • link-clicked:单机pdf内的链接会触发。
  1. <script>
  2. import pdf from 'vue-pdf'
  3. export default {
  4. name: 'Home',
  5. components: {
  6. pdf
  7. },
  8. data() {
  9. return {
  10. url: "http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf",
  11. pageNum: 1,
  12. pageTotalNum: 1,
  13. pageRotate: 0,
  14. // 加载进度
  15. loadedRatio: 0,
  16. curPageNum: 0,
  17. }
  18. },
  19. mounted: function() {},
  20. methods: {
  21. // 上一页函数,
  22. prePage() {
  23. var page = this.pageNum
  24. page = page > 1 ? page - 1 : this.pageTotalNum
  25. this.pageNum = page
  26. },
  27. // 下一页函数
  28. nextPage() {
  29. var page = this.pageNum
  30. page = page < this.pageTotalNum ? page + 1 : 1
  31. this.pageNum = page
  32. },
  33. // 页面顺时针翻转90度。
  34. clock() {
  35. this.pageRotate += 90
  36. },
  37. // 页面逆时针翻转90度。
  38. counterClock() {
  39. this.pageRotate -= 90
  40. },
  41. // 页面加载回调函数,其中e为当前页数
  42. pageLoaded(e) {
  43. this.curPageNum = e
  44. },
  45. // 其他的一些回调函数。
  46. pdfError(error) {
  47. console.error(error)
  48. },
  49. }
  50. }
  51. </script>

其他骚操作:

  1. // 打印全部
  2. pdfPrintAll() {
  3. this.$refs.pdf.print()
  4. },
  5. // 打印指定部分
  6. pdfPrint() {
  7. this.$refs.pdf.print(100, [1, 2])
  8. },

具体样式什么的我就不贴出来了,这些都不是重点,完全可以改成自己喜欢的。
成品展示:
vue-pdf 实现pdf在线预览 - 图1

其他问题以及解决方案:

如何加载本地pdf文件(2021.4.27更新):

评论区有人提到了这个问题,我今天中午的时候试了一下,完全是可以的,但是需要我们做一下本地配置flie-loader才行,否则webpack无法编译pdf类型的文件,配置方法也很简单,在项目根目录新建一个vue.config.js文件,我发现很多人直接就去babel.config.js这个文件里面配置,这样是不对的,肯定会报错,
先安装file-loader:
npm install --save file-loader

然后在vue.config.js中加入以下内容:

  1. module.exports = {
  2. chainWebpack: config => {
  3. const fileRule = config.module.rule('file')
  4. fileRule.uses.clear()
  5. fileRule
  6. .test(/\.pdf|ico$/)
  7. .use('file-loader')
  8. .loader('file-loader')
  9. .options({
  10. limit: 10000,
  11. })
  12. },
  13. publicPath: './'
  14. }

之后再url:require(“../assets/1.pdf”)就没有任何问题了,注意,vue-pdf src接收的是string对象,如果直接传url我这里报错了,你可能需要传url.default一下。

跨域问题:

网上用pdf.js 很多都会遇到跨域问题,这个我今天实际应用到自己的项目里面了,由于我服务端设置了跨域,所以没有出现跨域的问题,如果出现跨域需要修改你后端的请求头。

打印界面字符乱码:

这个我倒是碰到了,谷歌浏览器打印的时候,预览界面真的变成了 真·方块字 ,全是方块。这个问题是因为你pdf中使用了自定义字体导致的,具体解决方案如下:
首先,找到这个文件:node_modules/vue-pdf/src/pdfjsWrapper.js
然后根据github上这个issue,其中红色的是要删掉的,绿色的是要加上去的,照着改就可以解决了。
地址: github.com/FranckFreib…
根据我的实际测试,是可以解决打印乱码的问题的。