從去年年初開始,本身便下決心要寫一個vue系列的博客,但時至今日,才寫系列的第三篇博客,想來甚是慚愧。javascript
可是慢歸慢,每一篇都要保證質量,以及要寫出本身的心路歷程,防止本身工做中填的坑再讓讀者走一遍。html
vue上手相對react來講是比較簡單的,對於vue的基本指令以及語法,應該沒有什麼能比官網更詳細,更生動的了。仔細想來,vue值得一說的,在項目中會讓新手感到困惑的,是vue的組件,今天就最近工做中用到的一個pdf查看組件,和你們聊聊vue的組件。最後會講如何將本身的代碼封裝成一個npm包,發佈到npm官網。前端
去年5月份的,寫了vue系列的第一篇使用vue-cli腳手架工具搭建vue-webpack項目,今天再次使用vue-cli初始化項目時,發現vue-cli已經升級到2.9.2。vue
多說一句,由於vue-cli的命令爲vue,因此查看vue-cli的版本時,須要使用vue -V,並且是大寫的V。仔細看下vue-cli 2.9的官方模板,驚喜的發現多了一個pwa模板。java
前一陣子,谷歌開發者大會在上海舉辦,會上主推pwa,在這在簡單說下PWA,大神可直接忽略。react
PWA是Progressive Web App的縮寫,字面意思理解爲漸進加強的網頁應用。一個 PWA 應用首先是一個網頁, 能夠經過 Web 技術編寫出一個網頁應用. 隨後添加上 App Manifest 和 Service Worker 來實現 PWA 的安裝和離線等功能。jquery
在一個正常的HTML中,添加一個link標籤,href爲manifest.json,便可將你的網頁應用添加到主屏幕。webpack
manifest.json中會包含你的圖標、名稱。背景色等信息。git
{ "name": "你的web app名稱", "short_name": "簡稱", "display": "standalone", "start_url": "/", "theme_color": "主體色(#ffffff)", "background_color": "背景色(#333333)", "icons": [ { "src": "icon.png", "sizes": "256x256", "type": "image/png" } ] }
引入manifest.json
<link rel="manifest" href="manifest.json" />
PWA應用能實現離線訪問的核心是Service Worker,Service Worker 在網頁已經關閉的狀況下還能夠運行, 用來實現頁面的緩存和離線, 後臺通知等等功能。github
爲了讓應用離線工做,須要註冊一個 service worker,一段容許在後臺運行的腳本,不須要 用戶打開 web 頁面,也不須要其餘交互。在應用根目錄放置serviceworker.js,而後在瀏覽器註冊。
if('serviceWorker' in navigator) {
navigator.serviceWorker .register('/service-worker.js')
.then(function() { console.log('Service Worker Registered');
}); }
在serviceworker註冊後,瀏覽器首次訪問該應用時,會執行install方法,這個方法的callback中咱們可以緩存全部須要緩存的數據。具體過程爲:
首先定義須要緩存的文件類型,以及緩存存放路徑;而後在網頁相應全部請求以前,會將請求統一處理,能夠控制一部分請求從緩存裏拿數據。緩存會經過字符串名稱,動態的更新。篇幅有限,這裏大概簡述下。具體能夠移步餓了麼團隊知乎。
下面言歸正傳,說說vue組件。
最近筆者在項目中遇到一個pdf預覽的需求,通過調研,最終決定用火狐的pdf.js封裝一個vue組件。
其實需求仍是比較簡單的,就是後臺給一個URL,前端將pdf加載到網頁中便可。chrome和Firefox是自帶pdf查看器的,簡單的作法是使用iframe嵌入,但該方案兼容性太差,並且不受咱們控制,因此pass了。
1.經過pdf.js提供的api,咱們傳入pdf的URL,在callback中會拿到所需的pdf對象。
2.經過傳入不一樣的頁碼,能夠拿到指定頁面的page對象。
3.經過canvas,將page對象渲染到頁面中。
4.遍歷全部page,循環生成多個canvas對象,插入dom。
把思路縷清楚以後,開發就比較簡單了。
首先,肯定dom結構。因爲咱們的canvas是動態插入dom的,因此只提供一個wraper便可。
<template> <div class="pdf-wraper"> <div id="cvsWraper"> <div class="loading-pdf" v-if="isloading">{{loadingTxt}}</div> </div> </div> </template>
該組件須要傳兩個參數,一個是URL,一個是縮放值scale。
vue組件須要顯式說明自身指望傳入哪些屬性,而且能夠賦予默認值。調用組件時,傳入不一樣的屬性,能夠實現父組件向子組件傳值。
props: { pdfurl: { default: '' }, scale: { default: 1 } }
子組件向父組件通訊時,須要使用vue.$emit事件。
$emit事件接受兩個參數,第一個爲所要拋出的方法名,第二個爲所拋出方法帶的參數。
在這個組件中,只暴露出一個onErr事件,即當pdf加載失敗時的回調函數。
PDFJS.getDocument(me.pdfurl).then(function (pafObj) {
me.isloading = true;
me.pdfDoc = pafObj;
let totalNum = me.pdfDoc.numPages;
// 循環渲染全部canvas
for (let i = 1; i <= totalNum; i++) {
let id = `canvas${i}`;
let cvsNode = document.createElement('canvas');
cvsNode.setAttribute('id', id);
cvsNode.setAttribute('class', 'canvas-item');
cvsWraper.appendChild(cvsNode);
me.renderPage(i);
if (totalNum === i) {
me.isloading = false;
}
}
}).catch(function (err) {
me.loadingTxt = '加載失敗,請稍後重試';
me.$emit('onErr', err);
});
在調用組件時,須要傳入所需的屬性和方法。
<template>
<div>
<pdfshower
:pdfurl="pdfurls"
:scale="scale"
@onErr="onErr"
></pdfshower>
</div>
</template>
兄弟組件通訊也是比較常見的,好比說在一個頁面中,導航是一個組件,內容區域是一個組件;當導航切換時,須要通知內容組件發生變化,並告訴他導航的id。
處理兄弟組件通訊的問題,通常有兩種方式:
1.兄弟組件都引入一個公共vue組件hub,經過hub拋出事件,和監聽事件,以達到兄弟組件通訊。
2.使用vuex。
項目中比較常見的是第一種作法,我作的vue項目中只有一次使用到了vuex;我對vuex的理解是:
vuex相似於一個全局的存儲空間,你能夠把他理解爲將須要傳遞的東西綁在了window下,因此在任何地方均可以拿到,並作修改。
在項目中用到的hub.js
/** * @file 事件總線 * @author yangtianjiao / import Vue from 'vue'; export default new Vue({});
假設是上面說的那種狀況,在導航組件切換時,經過hub發射信息:
hub.$emit('changeTableData', { dateKey: this.curDateTab });
內容區域監聽hub發射的方法:
hub.$on('changeTableData', item => { this.pageNum = 1; this.total = 0; this.dataList = []; this.orderFieldId = 1; this.orderType = 1; this.contenctDesc = ''; this.emptyText = '數據加載中...'; this.isLoading = false; });
在內容組件銷燬時,取消對hub事件的監聽
beforeDestroy() { hub.$off('changeTableData'); }
兄弟組件通訊並不複雜,但要深入理解,必須在項目中多運用、實踐。這塊應該是vue最難的部分了,這塊掌握了,vue項目作起來就會駕輕就熟。
你們平時工做中,最經常使用的是npm,不少包、類庫都從npm安裝。其實咱們很容易就會發布屬於本身的npm包,下面我會一步步講講如何將上述的vue-pdf-viewer組件發佈到npm官網的。
執行npm init後,根據命令行提示,依次輸入
包名稱
版本
描述
入口文件
測試腳本
關鍵詞
做者
版權信息(協議)
等等,最後OK,生成一個package.json文件。
package.json是npm幫咱們生成的,根目錄下有入口文件index.js,和readme.md。
index.js中其實就是一句話,將真正的index.vue暴露出去
index.js
/** * @file vue-pdf-shower * @author v_yangtianjiao(v_yangtianjiao@baidu.com) * @time 18/01/15 */ module.exports = require('./lib/index.vue');
readme中放有對包的簡述,以及包的基本用法
readme.md
# vue-pdf-shower ## 介紹 > 基於pdf.js的pdf簡易查看組件。 > 該組件加載所有pdf頁面,不提供翻頁查看功能。 ## github [vue-pdf-shower](https://github.com/TJ666/vue-pdf-shower) ## install ``` npm i vue-pdf-shower --save ``` ## example ``` <template> <div> <pdfshower :pdfurl="pdfurls" :scale="scale" @onErr="onErr" ></pdfshower> </div> </template> <script> import pdfshower from 'vue-pdf-shower'; export default { name: 'pdfshower', components: { pdfshower }, data() { return { // 所查看的pdf url pdfurls: '//cdn.mozilla.net/pdfjs/tracemonkey.pdf', // 縮放 默認爲1 scale: 1.2 }; }, methods: { // 加載失敗的callback onErr(err) { console.log('pdf加載失敗,請重試'); console.log('錯誤信息:', err); } } }; </script> ```
至於爲啥有個lib文件夾,還有目錄結構爲啥長這樣?個人回答是:
看了一遍全部的npm包都是這樣,咱就按人家的來吧 - -
好了,我們的包已經準備就緒了,就差發布!!!
打開冰箱,將大象放進冰箱,關上冰箱門。
註冊很簡單的,只須要一個郵箱就行,連網站都打不開的同窗就好好寫寫jquery去吧。
在命令行輸入npm login,
而後依次輸入用戶名和密碼,以及註冊的郵箱。
注意:輸入密碼時,密碼是不會顯示出來的,不要方!
登陸後只要沒有錯誤提示即登陸成功。
離成功只差一步。
一切準備穩當,cd 到咱們的vue-pdf-shower目錄,先檢查下npm有沒有重名的包。
能夠去npm官網搜索,也能夠直接npm install 包名,若是報錯,那麼恭喜你包名沒有重複的。
執行npm publish
定睛一看,報了個錯。原來是package.json 的版本號沒有改。將版本號升一個級,在執行publish。
成功!
發現已經能夠搜到,由於我是昨天發的包,一天時間內已有116次下載。嗯,還不賴。
最後附上本組件github地址,歡迎你們拍磚。
https://github.com/TJ666/vue-pdf-shower