作vue開發,基本的操做會了以後是否是特想擼一擼vue的插件,讓本身的代碼可(騷)復(騷)用(的)。別急,今天和你一塊兒手摸手,哦呸,是手把手,一塊兒擼一管,哦再呸,是封裝一個基於vue的支付寶密碼彈窗插件。而後還會介紹如何書寫插件的markdown說明文檔、發佈到github、在github設置項目的運行地址、發佈npm包。javascript
簡單看下效果圖,主要實現密碼輸入完成自動觸發輸入完成的回調函數,自定義標題、自定義高亮顏色、自定義加載動畫,密碼錯誤彈窗,可清空密碼等基本操做。html
開發vue插件以前呢,先說下封裝插件的目的是什麼?封裝插件的目的就是爲了代碼的可複用,既然是爲了可複用,那麼只要能實現可複用的操做,封裝方式就能夠多樣化。這和jq的$.fn.myPlugin =
function(){}
有些區別。先來看下官方文檔對於vue插件的說明:vue
插件一般會爲 Vue 添加全局功能。插件的範圍沒有限制——通常有下面幾種:java
添加全局方法或者屬性,如: vue-custom-elementnode
添加全局資源:指令/過濾器/過渡等,如 vue-touchgit
經過全局 mixin 方法添加一些組件選項,如: vue-routergithub
添加 Vue 實例方法,經過把它們添加到 Vue.prototype 上實現。算法
一個庫,提供本身的 API,同時提供上面提到的一個或多個功能,如 vue-routervue-router
MyPlugin.install = function (Vue, options) {
// 第一種方法. 添加全局方法或屬性
Vue.myGlobalMethod = function () {
// 邏輯...
}
// 第二種方法. 添加全局資源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 邏輯...
}
...
})
// 第三種方法. 注入組件
Vue.mixin({
created: function () {
// 邏輯...
}
...
})
// 第五種方法. 添加實例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 邏輯...
}
// 第六種方法,註冊組件
Vue.component(組件名, 組件)
}複製代碼 |
這些形式均可以做爲咱們的插件開發。插件的本質不就是爲了代碼的複用嗎?根據你的封裝需求選擇不一樣的形式,例如toast提示
能夠選擇Vue.prototype
,輸入框自動獲取焦點能夠選擇Vue.directive
指令,自定義組件能夠選擇Vue.component
的形式。vue-cli
由於咱們的支付密碼框能夠看做爲一個組件,因此纔有Vue.compnent
的形式。下面開始搭建基本的一個殼:
爲了你們能看到項目運行起來,先初始化一個vue的項目。而後在src新建一個lib文件夾用於存放各個插件,在lib下新建一個vpay文件夾存放咱們的插件。
在vpay文件夾下,新建一個index.js和一個lib文件夾,而咱們真正的插件是寫在新建的這個lib文件夾中的。這裏之因此這麼建立是由於後面還有在這裏初始化npm包,發佈到npm上:
暫時先無論npm包的內容,這個最後再說。先看插件這一塊,根據上述內容建立對應文件。
而後咱們開始搭建插件開發的基本殼子,在插件的index.js中:
// pay.vue寫咱們的組件
import vpay from './pay'
// 定義咱們的插件
const myPlugin = {
// 該插件有一個install方法
// 方法的第一個參數是傳入的Vue,第二個參數能夠插件的自定義參數
install (Vue, options) {
// 將其註冊爲vue的組件,'vpay'是組件名,keyboard是咱們開發的組件
Vue.component('vpay', vpay)
}
}
// 最後將插件導出,並在main.js中經過Vue.use()便可使用插件
export default myPlugin複製代碼
待插件開發好後,就能夠在mian.js中這樣使用:
// 引入插件
import vpay from './lib/vpay'
// 使用插件
Vue.use(vpay);複製代碼
然後在咱們的頁面中就能夠直接像使用組件的方式使用插件:
<!--支付密碼彈窗-->
<vpay
ref="pays"
v-model="show"
@close="close"
@forget="forget"
@input-end="inputEnd"
></vpay>複製代碼
是否是跟咱們平時使用插件的形式一模一樣?基本思路和插件的殼子有了,下面就開始開發pay.vue,這插件的具體內容了。這部分的開發,說的簡單些,其實就和平時寫個父子組件般,由於咱們最後想向上面那種自定義組件的形式使用。
pay.vue文件:
<template>
<div class="zfb-pay" v-if="show">
<div class="content">
<!--標題欄-->
<header class="pay-title">
<div class="ico-back" @click="cancel"></div>
<h3>{{title}}</h3>
</header>
<!--密碼框-->
<div class="pass-box">
<ul class="pass-area">
<li class="pass-item"
:class="{on: password.length > index}"
v-for="(item, index) in digit"
:key="index"></li>
</ul>
</div>
<!--忘記密碼-->
<div class="forget-pass">
<div class="forget-pass-btn" @click="forget">忘記密碼</div>
</div>
<!--鍵盤區-->
<ul class="keyboard">
<li @click="onKeyboard(1)">
<p class="num"><strong>1</strong></p>
<p class="character"></p>
</li>
<li @click="onKeyboard(2)">
<p class="num"><strong>2</strong></p>
<p class="character">ABC</p>
</li>
<li @click="onKeyboard(3)">
<p class="num"><strong>3</strong></p>
<p class="character">DEF</p>
</li>
<li @click="onKeyboard(4)">
<p class="num"><strong>4</strong></p>
<p class="character">GHI</p>
</li>
<li @click="onKeyboard(5)">
<p class="num"><strong>5</strong></p>
<p class="character">JKL</p>
</li>
<li @click="onKeyboard(6)">
<p class="num"><strong>1</strong></p>
<p class="character">MNO</p>
</li>
<li @click="onKeyboard(7)">
<p class="num"><strong>7</strong></p>
<p class="character">PQRS</p>
</li>
<li @click="onKeyboard(8)">
<p class="num"><strong>8</strong></p>
<p class="character">TUV</p>
</li>
<li @click="onKeyboard(9)">
<p class="num"><strong>9</strong></p>
<p class="character">WXYZ</p>
</li>
<li class="none"></li>
<li class="zero" @click="onKeyboard(0)"><strong>0</strong></li>
<li class="delete" @click="deleteKey"></li>
</ul>
<!--加載中狀態-->
<div class="loading-wrap" v-if="payStatus !== 0">
<div class="loading">
<!--加載圖標-->
<img src="@/assets/loading.png" class="loading-ico" alt="" v-if="payStatus === 1">
<img src="@/assets/success.png" class="success-ico" alt="" v-if="payStatus === 2">
<!--加載文字-->
<p v-if="payStatus === 1">{{loadingText}}</p>
<p v-if="payStatus === 2">{{finishedText}}</p>
</div>
</div>
<!--支付失敗提示框-->
<div class="pay-fail" v-if="isShowFail">
<div class="pay-fail-lay">
<h3 class="title">{{failTip}}</h3>
<div class="btns">
<div @click="reInput">從新輸入</div>
<div @click="forget">忘記密碼</div>
</div>
</div>
</div>
</div>
</div>
</template>複製代碼
佈局沒什麼可說的,大致說下分爲哪些板塊吧:
this.$refs.pays.$success(true).then(res => {})
告知插件成功結果並在成功提示停留結束後觸發then
裏面的操做。this.$refs.pays.$fail(false)
調用插件的方法告知插件支付結果爲密碼錯誤,插件會彈出錯誤的提示框。以上代碼因爲是已經寫好了插件而後直接拷貝的,因此上面插入了變量和方法等。佈局完成後,下面開始介紹實現:
export default {
data() {
return {
password: '', // 支付密碼
payStatus: 0, // 支付狀態,0無狀態, 1正在支付,2支付成功
failTip: '支付密碼錯誤', //
isShowFail: false
}
},
}複製代碼
onKeyboard
方法:
// 點擊密碼操做
onKeyboard(key) {
// 只截取前六位密碼
this.password = (this.password + key).slice(0, 6);
},複製代碼
同時經過在watch鉤子裏面,監聽password,在password長度達到設置的長度後(例如輸入完6位後)經過$emit('input-end')通知父組件的自定義事件,能夠理解爲輸入完成後的回調函數:
watch: {
// 監聽支付密碼,支付密碼輸入完成後觸發input-end回調
// 通知父組件的同時會把輸入完成的密碼做爲參數告知父組件,即input-end函數的參數能拿到密碼
password (n, o) {
if (n.length === this.digit) {
this.payStatus = 1;
this.$emit('input-end', this.password)
}
}
},複製代碼
this.digit是經過prop傳遞的值,用於設置支付密碼框的位數,默認六位:
// 支付密碼框位數
props: {
// 支付密碼框位數 digit: {
type: Number,
default: 6
},
}複製代碼
2. 完成了密碼的輸入,開始作密碼的回刪,即每次回刪,刪除password的最後一位數,有點相似算法裏面的堆(後進先出),有點扯遠了,這裏用不到:
// methods中的方法,密碼回刪
deleteKey(){
// 密碼已經爲空時,不回刪
if (this.password.length === 0) return;
// 回刪一位密碼
this.password = this.password.slice(0, this.password.length - 1);
},複製代碼
密碼長度爲0時再也不回刪,不爲0時每次截取0到長度減一的位置爲新密碼,即去掉了最後一位密碼。
3.說到了密碼輸入達到指定的長度後會自動觸發父組件的自定義事件,這個是寫在父組件的,等下演示調用插件的時候會介紹。那麼對應的也會有取消支付彈窗的操做,即點擊彈窗左上角的返回按鈕取消支付,關閉彈窗:
// 取消支付
cancel () {
// 支付過程當中,不容許取消支付
if (this.payStatus === 1) return;
// 清空密碼
this.password = '';
// 恢復支付狀態
this.payStatus = 0;
// 關閉組件,並觸發父子組件數據同步
this.$emit('change', false);
// 觸發父組件close自定義事件
this.$emit('close');
},複製代碼
取消的時候首先要判斷當前的支付狀態,若是是正在支付的狀態,則是不容許取消的。這裏的在data中已經有過定義,主要payStatus有三個值:0無狀態,1支付中,2支付成功。而後就是清空密碼、初始化支付的狀態、關閉彈窗、同時告知父組件使得父組件能夠有一個close的自定義事件寫回調函數。
因爲支付彈窗的顯示隱藏是由父組件傳遞的值控制的,因此這裏在組件內改變了父組件傳遞的值後也要對應的更新父組件的值,即this.$emit('change', false)
:
如圖咱們在使用插件的時候,想經過v-model的值來控制組件的顯示隱藏,就像不少庫同樣使用v-model。因此這裏展現如何操做能經過v-model實現:
仍是組件的prop屬性,經過prop的show屬性來控制組件的顯示隱藏:
// 組件的顯示隱藏
show: {
type: Boolean,
required: true,
default: false
},複製代碼
而後在model的鉤子中:
model: {
prop: 'show',
event: 'change'
},複製代碼
最後是在html中經過該字段控制顯示隱藏。v-model的內容這裏很少作介紹,回頭這裏更新一個鏈接地址,在另外一篇裏面有詳細的介紹。
4. 下面就是當你密碼輸入完成後,自動觸發父組件的input-end回調,你在input-end回調中發起了支付請求,這時後臺會返回給你支付狀態,例如支付成功或者密碼錯誤。未設置支付能夠在吊起支付彈窗之前就去判斷或者提示。當你拿到支付的結果後,要經過調用插件的$success
方法或者$fail
方法告知插件你的支付結果。以下圖咱們先看怎麼使用的,而後再說怎麼在插件中實現$success
方法和$fail
方法:
調用pay-keyboard
的時候,定義了ref="key"
,因而咱們就能夠經過this.$refs.pay
指向當前插件實例。用法很簡單,註釋寫的也比較清楚就不解釋了。下面是插件的$success方法:
//支付成功
$success () {
return new Promise((resolve, reject) => {
// 支付成功當即顯示成功狀態
this.payStatus = 2;
// 待指定間隔後,隱藏整個支付彈窗,並resolve
setTimeout(() => {
this.cancel();
resolve();
}, this.duration);
})
},複製代碼
該方法返回一個promise對象,promise會當即執行。返回promise
是爲了調用時經過then
方法寫回調,更優雅一些。在promise
內,進行了支付狀態的更改,而後在設置的支付成功狀態顯示的時間結束後關閉彈出並resolve
。因此this.$refs.pay.$success().then()
方法中的操做會在等待成功提示結束、也就是彈窗隱藏掉以後執行。
// 支付失敗
// 隱藏加載提示框,顯示支付失敗確認框
$fail (tip) {
tip && typeof tip === 'string' && (this.failTip = tip);
// 隱藏掉支付狀態窗口
this.payStatus = 0;
// 顯示密碼錯誤彈窗
this.isShowFail = true;
},複製代碼
$fail
方法就是插件在得知支付結果爲密碼錯誤的時候,顯示出密碼錯誤的彈窗。密碼錯誤彈窗的提示是可自定義的。經過tip參數獲取自定義的錯誤提示。
該錯誤提示彈窗,有兩個按鈕,有一個從新輸入,一個忘記密碼。
點擊從新輸入,確定是要隱藏該彈窗,而後狀況已經輸入的密碼。由此,在methods中寫一個reInput方法來實現該功能:
// 從新輸入
// 清空以前輸入的密碼,隱藏支付失敗的提示框
reInput () {
this.password = '';
this.isShowFail = false;
},複製代碼
這樣就能夠從新輸入支付密碼了。
忘記密碼,這裏咱們能夠將點擊後操做的控制權交給父組件。因此,咱們寫一個忘記密碼的點擊後的方法,這裏的忘記忘記密碼能夠和上面密碼區的忘記密碼做爲同一個操做。固然了你也根據本身的需求開發出區分開的操做。這裏是做爲同一個的操做:
// 忘記密碼,觸發父組件的forget自定義事件
forget () {
this.$emit('forget');
}複製代碼
由此,即可以在父組件的@forget自定義事件中進行一個鏈接的跳轉等操做。
固然了,咱們的prop接收的參數還有如下這些:
// 彈窗標題
title: {
type: String,
default: '請輸入支付密碼'
},
// 正在支付的文字提示
loadingText: {
type: String,
default: '正在支付'
},
// 支付成功的文字提示
finishedText: {
type: String,
default: '支付成功'
},
// 支付成功的提示顯示時間
duration: {
type: Number,
default: 500
}複製代碼
經過這些prop參數,咱們能夠在初始化插件的時候進行配置。
插件開發完成後就是調用啦,在咱們的main.js中先引入咱們的插件,然後進行初始化插件:
// 引入插件,位置是你的插件位置
import payPassword from './lib/zfc-password'
// 初始化插件
Vue.use(payPassword)複製代碼
而後在咱們的頁面內這樣使用:
<vpay
v-model="show"
ref="pays"
@close="close"
@forget="forget"
@input-end="inputEnd"
></vpay>
複製代碼
到此咱們的插件基本就開發完成了。已經提交github,送上github項目地址和demo地址,自行查閱。
是否是很熟悉呢!沒錯,這就是markdown格式的說明文檔。說到markdown,其實也很多內容的,可是咱們只說一些經常使用的寫markdown文檔的語法,這些已經足夠咱們平時寫文檔用了。
Markdown 是一種輕量級標記語言,創始人爲約翰·格魯伯(John Gruber)。它容許人們「使用易讀易寫的純文本格式編寫文檔,而後轉換成有效的XHTML(或者HTML)文檔」。這種語言吸取了不少在電子郵件中已有的純文本標記的特性。
markdown使用途徑好久,不少寫做等都是使用的markdown文檔,包括咱們的掘金寫做也是能夠切換markdown妥當的。下面就說說markdown的常見語法吧。在咱們vue建立的根目錄,你會發現有一個reaame.md文件,這個文件就能夠用來書寫項目的說明文檔。若是項目傳到github上面,這個文檔對應的就是如上圖所示的使用文檔說明。
markdown文檔每種格式都有其餘的書寫方式,這裏只介紹其中常見的一種或者說話是我的比較喜歡的形式:
# 一級標題
## 二級標題
### 三級標題
#### 四級標題
##### 五級標題
###### 六級標題複製代碼
效果圖:
* 1111
* 2222
* 3333
1. 1111
2. 2222
3. 33334. 4444複製代碼
效果圖:
| 事件名 | 說明 | 參數 |
| - | :- | :- | :-: |
| input-end | 密碼輸入完成後的回調函數 | - |
| close | 密碼彈窗關閉後的回調函數 | - |
| forget | 點擊忘記密碼的回調函數 | - |複製代碼
表格這裏說一下,第一行對應表格的標題,第二行將表格標題和表格內容分開,而且在這裏能夠定義表格對齊方式,即| - | 默認左對齊,| :- |在左邊添加:
表示這一列左對齊,右邊加:
則這一列右對齊,兩邊都加:
則居中對齊。
```javascript
this.$refs.pays.$success(true).then(res => {
console.log('支付成功')
this.$router.push('/success')
})
```複製代碼
即兩個```
之間能夠添加代碼塊。是esc按鍵下的那個鍵,不是單引號。
![支付密碼框演示動圖](./static/pay.gif)複製代碼
經過![圖片說明](圖片路徑)
即可以引入圖片。效果如上圖演示的動態圖。
[demo演示頁面](https://chinaberg.github.io/vpay/dist/#/, '支付密碼彈窗demo演示頁面')複製代碼
[]
設置連接名稱,()
中第一個參數爲連接地址,第二個參數爲連接的title
屬性值,第二個參數可選。效果如圖:
markdown文檔的書寫語法暫且介紹這些最最經常使用的一些。更多的markdown語法,請查看相關文檔。
插件開發好了,文檔說明也寫好了,下面就是上傳github、設置github的項目展現頁,而後分享給更多的人。
git init
初始化git項目git checkout -b master
新建一個master分支git
忽略監控咱們打包後的dist文件夾,因此這裏我要取消忽略,讓git
監控dist
文件夾,否則提交遠程庫的時候不會提交dist
文件夾:打開根目錄下的.gitignore文件,這是git的配置文件,能夠在這裏設置git不須要監控的文件類型。因此咱們在這裏把/dist/
這行代碼刪除,這樣,後面咱們再git add .
的時候就會監控dist
文件夾了。此時若是運行git status命令,能夠看到git已經開始監控dis文件夾了git add .
注意,這裏有一個點,並且點和add直接有空格。git commit -m"初始化支付寶密碼彈窗"
git本地提交git remote add origin git@github.com:chinaBerg/my-project.git
,後面的地址是你的遠程庫的ssh地址,這裏不要拷貝個人地址了,你鏈接個人遠程庫是不會成功的。而後運行git remote -v
查看一下是否鏈接成功:能夠看到個人遠程庫已經鏈接成功了。下面就開始講本地的代碼推送到遠程庫。第一次提交,因爲本地的分支沒有和遠程的分支進行關聯,因此咱們第一次push的時候,要先關聯遠程庫:git push -u origin master
, 其中-u origin master
表示將當前的分支關聯到遠程的master分支,這樣你提交的時候當前的本地分支的內容就會提交到遠程的master分支上。
能夠看到已經提交成功了。接下來咱們打開github上面的項目看下,刷新後看到,項目以上傳到遠程了,其中既有咱們的源碼,也有打包後的dist文件,也有咱們以前寫好的readme.md說明文檔:
文件上傳之後,咱們怎麼設置才能在github上查看運行的項目的呢?
在當前項目中,點擊setttings選項,選擇Options選項卡,拉倒底部的位置,找到GitHub Pages區域,點擊下拉菜單將選擇master branch選項,而後點擊save按鈕保存。
而後咱們就會看到,這個位置有一個url地址。沒錯,這個就是咱們的項目路徑,可是呢,咱們打包後能容許的項目是在dist文件夾下,因此咱們想訪問打包後的項目的話,只要在這個路徑後面拼接,例如:https://chinaberg.github.io/my-project/dist/index.html 你如今訪問我這個項目可能不存在了,由於我已經刪除了。
至此,咱們上傳github的操做已經完成了。
其實這裏主要用到的知識就是git的使用。使用git對咱們的代碼進行版本控制和鏈接遠程庫等,都是咱們做爲開發人員基本必需要會的一項技能,但願還不會git的小夥伴要抽點時間學習一下。否則這裏估計會坑的想放棄呢!
咱們已經把插件代碼上傳到github上面了,那麼咱們是否能夠也作成一個npm包發佈到npm上呢?答案是確定的,如此一次,咱們在須要使用到該插件的時候就能夠直接npm i vpay
等的實現安裝到咱們的項目中,豈不是很方便呢?
正如文章剛開始提到的文件目錄,咱們是把插件都寫在了第二個lib中的。而整個vpay文件夾都是咱們要做爲npm包發佈的。其中readme.md是說明文檔,跟github上的同樣,你能夠簡單的先拷貝根目錄下的那個。
而後是vpay文件下面的index.js,裏面就依據代碼,即導出咱們的插件:
module.exports = require('./lib')複製代碼
因爲咱們在使用插件的時候, 其實引入的就是這個index.js,因此在這個文件中,咱們導出了咱們的插件。
而下面重點要說的是這個package.json文件,這個一開始是沒有的,這是npm包的配置文件。咱們要首先進入vpay文件夾的位置,而後終端運行npm init
命令來初始化一個npm包配置文件,此時他會問你一些列問題來完成配置文件:
Index.js
,能夠自定義。.git
目錄做爲這一項的默認值。沒使用則回車略過。到這一步,其實咱們已經作好了本地包的開發,咱們要測試一下包能不能使用。怎麼測試呢?咱們知道,平時是使用npm安裝插件的時候,實際上是把插件安裝在了根目錄下的node_modules文件中。那麼,咱們既然已經開發好了本地包,咱們就把這個vpay文件夾直接拷貝到node_modules文件夾中。而後在main.js中像平時同樣使用插件:
// 直接引入vpay,不須要寫路徑
import vpay from 'vpay'
Vue.use(vpay);複製代碼
測試一看,一切正常,說明咱們的包是沒問題的。
下面就是要發佈了。發佈以前,咱們首先要有一個npm的帳號,若是你尚未帳號的,自行去npmjs官網註冊一個帳號,這裏提示一下,註冊用戶名的時候常常可能不經過,因此仍是字母開頭加一些數字方便些。這裏的full name 能夠理解爲暱稱,email郵箱,後面兩個是用戶名和密碼。有些時候用戶名老是會提示不合規範,因此仍是字母加數字快些。
迴歸正題,先切換到咱們的vpay文件目錄,而後執行npm login命令登陸咱們的npm帳號,他會提示你輸入npm的用戶名和密碼,注意輸入密碼的時候不會有任何提示,這裏不要覺得是否是沒有反應。你只管輸入就好,只不過什麼都看不到,輸入完成回車,而後輸入npm的郵箱。最後回車,這裏有一點要注意的,若是你是以前安裝了淘寶鏡像,那是不會成功的,由於你的要把npm包發佈到npm鏡像上,而不是淘寶的鏡像。咱們平時能夠經過淘寶鏡像來加快下載速度,由於淘寶鏡像其實就是每隔十分鐘把npm的上的最新資源同步到本身身上而已。因此你要經過npm的鏡像登陸和發佈。
若是配置了淘寶鏡像,先設置回npm鏡像:
npm config set registry http://registry.npmjs.org 複製代碼
而後在終端執行npm login
命令:
看到最後一行Logged in as ……
就說明登陸成功了。
登陸成功後,運行npm publish
命令將npm包發佈到npm上。
這樣就發佈成功了。咱們去npm官網查一下咱們的包:
若是發佈成功後沒有搜到,就稍微等幾分鐘。
點擊進去看下,一切正常。之後就直接能夠經過npm i vpay將插件撞到咱們的項目中了。
到這,咱們基本已經完成了插件從開發、到寫說明文檔、再到發佈github、最後發佈npm包,一切已經能夠正常使用了。插件的個別地方的樣式有些略顯粗糙,可是本文的主要目的在於演示插件的開發過程。但願能對有須要的小夥伴起到幫助。
❤若是以爲喜歡就收藏一下或者start一下唄~~❤