前言
這里用到了vue-pdf
插件,預覽PDF相關的操作基本都有實現;
我們需要做的就是各種布局(因為需兼容已有的布局,有的地方可能需要修改),比如翻頁按鈕,頁碼展示等等;
vue-pdf的GitHub地址:FranckFreiburger/vue-pdf: vue.js pdf viewer (github.com)
目錄
- 入門例子
- 展示所有頁碼
- 翻頁操作
- 封裝組件
- 完整代碼
正文
1. 入門例子
安裝命令:yarn add vue-pdf
最簡單的入門例子,如下所示:
<template>
<pdf src="/pdf/1.pdf"></pdf>
</template>
<script>
import pdf from 'vue-pdf'
export default {
components: {
pdf
}
}
關於本地文件的路徑問題:
這里需要注意一下,要把pdf放在public目錄下,然后通過/
進行引用;
比如你的pdf路徑為:public/pdf/1.pdf
,那么src就要寫成:/pdf/1.pdf
;
如果是遠程路徑,則直接賦值;
2. 展示所有頁碼
上面的入門例子只是展示了第一頁的內容,其他內容沒有展示,如果需要展示其他頁,則需要添加翻頁功能;
但是現在我們先簡化,不添加翻頁功能,而是用v-for直接展示所有的頁碼;
<template>
<div>
<pdf
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
style="display: inline-block; width: 25%"
></pdf>
</div>
</template>
<script>
import pdf from 'vue-pdf'
var loadingTask = pdf.createLoadingTask('/pdf/1.pdf');
export default {
components: {
pdf
},
data() {
return {
src: loadingTask,
numPages: undefined,
}
},
mounted() {
this.src.promise.then(pdf => {
this.numPages = pdf.numPages;
});
}
}
</script>
展示效果如下所示:
當我們的頁碼不是很多時,可以采用這種簡單粗暴的方式進行展示,很方便;
但是如果頁碼過多,則不僅看起來很費勁,而且加載也會很慢,這時就需要用到翻頁功能;
3. 翻頁操作
這里主要增加兩個按鈕,以及相關屬性,下面是部分代碼:
<a-list-item>
<div @click="changePdfPage('pre')"
:style="currentPage===1?'cursor: not-allowed;':''">
上一頁
</div>
</a-list-item>
<a-list-item>
<div @click="changePdfPage('next')"
:style="currentPage===pageCount?'cursor: not-allowed;':''">
下一頁
</div>
</a-list-item>
<pdf :src="srcPdf"
:page="currentPage"
@num-pages="pageCount=$event"
style="display: inline-block;width:100%"></pdf>
- @num-pages 事件:獲取pdf的總頁數,這里獲取到之后傳給了pageCount
- page 屬性:就是當前頁碼,這里通過點擊上一頁和下一頁來修改來更新頁碼
效果如下所示:
完整代碼見下面;
4. 封裝組件
為了方便使用,我們可以將上面的預覽代碼封裝成功一個單文件組件,然后在需要的地方進行引入即可;
封裝后的組件代碼貼到文末了,因為有點長:
我們在展示pdf文件時,可以通過跳轉到新標簽頁的方式進行展示,這樣組件內的布局不會有太大的變化;
跳轉代碼如下所示:
let routeUrl = this.$router.resolve({
path: '/preview-pdf',
query:{pdfPath}
})
window.open(routeUrl.href, '_blank')
-
/preview-pdf
:這個路徑就是配置在路由里面的,預覽pdf的路徑 -
pdfPath
:這里我們是通過query的方式進行傳參,然后在預覽組件內通過this.srcPdf = decodeURIComponent(this.$route.query.pdfPath)
進行獲取;-
因為存在編碼問題,所以這里需要加上解碼操作;
如果pdf路徑是http遠程路徑,則不需要解碼
-
5. 完整代碼
完整的封裝組件如下,這里是參考網上的例子,做了一些修改
<template>
<div id="container">
<!-- 上一頁、下一頁 -->
<div class="right-btn">
<a-space>
<a-list>
<a-list-item>
<div >
<input v-model.number="currentPage"
type="number"
class="inputNumber"
@input="inputEvent()"> / {{pageCount}}
</div>
</a-list-item>
<a-list-item>
<div @click="changePdfPage('first')"
>
首頁
</div>
</a-list-item>
<a-list-item>
<!-- 在按鈕不符合條件時禁用 -->
<div @click="changePdfPage('pre')"
:style="currentPage===1?'cursor: not-allowed;':''">
上一頁
</div>
</a-list-item>
<a-list-item>
<div @click="changePdfPage('next')"
:style="currentPage===pageCount?'cursor: not-allowed;':''">
下一頁
</div>
</a-list-item>
<a-list-item>
<div @click="changePdfPage('last')"
>
尾頁
</div>
</a-list-item>
</a-list>
</a-space>
</div>
<div class="pdfArea">
<pdf :src="srcPdf"
ref="pdf"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
@link-clicked="currentPage = $event"
style="display: inline-block;width:100%"></pdf>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf'
export default {
components: {
pdf
},
computed: {
},
created () {
console.log('query:', this.$route.query)
this.srcPdf = decodeURIComponent(this.$route.query.pdfPath)
},
destroyed () {
},
mounted () {
},
data () {
return {
// ----- vuepdf -----
// src靜態路徑: /static/xxx.pdf
// src服務器路徑: 'http://.../xxx.pdf'
// src: srcPdf,
// 當前頁數
currentPage: 0,
// 總頁數
pageCount: 0,
// 加載進度
loadedRatio: 0
}
},
methods: {
// 頁面回到頂部
toTop () {
document.getElementById('container').scrollTop = 0
},
// 輸入頁碼時校驗
inputEvent () {
if (this.currentPage > this.pageCount) {
// 1. 大於max
this.currentPage = this.pageCount
} else if (this.currentPage < 1) {
// 2. 小於min
this.currentPage = 1
}
},
// 切換頁數
changePdfPage (val) {
if (val === 'pre' && this.currentPage > 1) {
// 切換后頁面回到頂部
this.currentPage--
this.toTop()
} else if (val === 'next' && this.currentPage < this.pageCount) {
this.currentPage++
this.toTop()
} else if (val === 'first') {
this.currentPage = 1
this.toTop()
} else if (val === 'last' && this.currentPage < this.pageCount) {
this.currentPage = this.pageCount
this.toTop()
}
},
// pdf加載時
loadPdfHandler (e) {
// 加載的時候先加載第一頁
this.currentPage = 1
},
}
}
</script>
<style scoped>
#container {
overflow: auto;
font-family: PingFang SC;
width: 100%;
display: flex;
position: relative;
}
/* 功能按鈕區 */
.right-btn {
right:4rem;
position: fixed;
display: flex;
flex-wrap: wrap;
justify-content: center;
z-index: 99;
}
.pdfArea {
width: 80%;
}
/*在谷歌下移除input[number]的上下箭頭*/
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
/*在firefox下移除input[number]的上下箭頭*/
input[type='number'] {
-moz-appearance: textfield;
}
.inputNumber {
border-radius: 8px;
border: 1px solid #999999;
font-size: 18px;
width: 2rem;
text-align: center;
}
.inputNumber:focus {
border: 1px solid #00aeff;
background-color: rgba(18, 163, 230, 0.096);
outline: none;
transition: 0.2s;
}
</style>
如何使用?
先注冊路由:src/router/index.js
import MyPdf from '../components/MyPdf'
export default new VueRouter({
routes: [
{
path: '/apply-contract-pdf',
name: 'apply-contract-pdf',
component: MyPdf
},
]})
再通過如下方法進行預覽:
previewPdf(pdfPath){
let routeUrl = this.$router.resolve({
path: '/preview-pdf',
query:{pdfPath}
})
window.open(routeUrl.href, '_blank')
},
總結
本篇介紹了vue-pdf的一些簡單使用,包括首頁展示、分頁展示等;
其實還有一些進度條展示這里沒列出來,感興趣的可以配合a-progress
組件和progress
屬性進行體驗