DEMO
配合著原始碼,用心看完這遍文章,你便領悟了封裝的精髓,麻雀雖小,五臟俱全。
前記
業務程式碼之外的程式碼,我想稱之為增值程式碼。
什麼意思?
作為一個程式設計師,你應該除了完成領導安排的任務,你還應該有一些自己的時間,用來“玩”一些比較有意思的事情。
當現有框架、庫滿足不了我們需求的時候,我們應該嘗試去自己造一些工具。也正是這些你所實現的,成就了他人,造就了自己。
不信,你且想一想,他人會關心你寫的具體的業務邏輯程式碼嗎?我想他們更關心的是,你寫的外掛,是如何使用的吧,以及方不方便他們藉此完成他們自己業務程式碼。
再通俗一點,他們不會記住你,但是他們會記住你的Api,因而憶起你。
還有很重要的一點,所有的技術,都是服務於業務的,否則,就是扯皮。
背景
入職新公司以來,一直忙於開發業務,過程中,多處用到了領導寫的牛逼工具。說實話,內心由衷的佩服,簡直就是解放生產力,放到古代,就是要被封神滴。
舉個例子:
領導花了一段時間,研究出了一個自動錶單生成器。之前手寫一個表單配置頁,加上表單驗證,可能需要半天,甚至更久。
現在呢?所有的表單、樣式及驗證,都可以通過程式碼配置實現,二十分鐘可能就完成了。
由此,我悟出了一個道理:
重複地做一件事,不如用心地做“一件事”。
我想,你肯定也想成為他人口中的那個男人,但整天活在自己的世界裡,你可能一時並不知道該如何去做,這裡我想告訴你:
成長的一個關鍵性因素,就是來自於模仿。
對的,你可以先嚐試著去閱讀下他人的程式碼,看看別人的實現方式,再者可以去github上溜一圈,優秀專案太多了,仿著寫去唄。
只要你想學,你就一定能學會,只不過是實現的方式好與壞而已,這些是需要後期不斷完善的。
鑑於本遍文章快要跑題了,不再多述,進入正題...
正文
1.元件和外掛的區別與聯絡
區別
- 元件的使用頻率往往大於外掛
- 元件的作用範圍往往小於外掛
聯絡
- 外掛可以封裝元件,元件可以暴露資料給外掛
這裡不做過多闡述,有興趣可以參考下勞卜大大的這編文章,寫的很通俗易懂。
2.實現外掛的必備因素
基礎
你需要清楚的知道vue的一些高階知識點以及相關內容,比如
- Vue.extend構造器
- $mount手動掛載例項
- mixin混合注入
- 父子元件傳參、跨級元件傳參
- 理解Vue建構函式及prototype原形物件
- npm官網註冊賬號
- webpack打包
- ...
技巧
以下這個技巧是今天開發的時候悟出來的,目測很有用:
彆著急開發,先想著如何在開發中使用你的外掛
什麼意思?順著我的思路捋下去
因為我想實現一個全域性toast外掛,大概用法
this.$toast('那個男人')
// todo
複製程式碼
光彈出文案不行,應該有一個控制彈出方向的變數
this.$toast('那個男人',{
position:'topCenter'
})
複製程式碼
全域性toast的狀態應該有多種,比如常見的成功
、錯誤
、警告
、普通
...
// 成功success
// 錯誤error
// 警告warning
// 普通info
this.$toast('那個男人',{
position:'topCenter',
type:'success'
})
複製程式碼
應該有一個時間變數去控制多長時間自動消失toast
this.$toast('那個男人',{
position:'topCenter',
type:'success',
closeTime: 3 // 控制3秒後消失toast
})
複製程式碼
會不會存在一種業務場景,我們不需要自動消失toast
this.$toast('那個男人',{
position:'topCenter',
type:'success',
closeTime: 3 // 控制3秒後消失toast
autoClose: false
})
複製程式碼
如果我想在toast結束後,觸發一些回撥動作,比如刪除成功toast後重新整理列表頁面
this.$toast('那個男人',{
position:'topCenter',
type:'success',
closeTime: 3 // 控制3秒後消失toast
autoClose: true,
callback () {
...
}
})
複製程式碼
toast的內容,可能會很長,因此應該有兩個變數分別控制toast寬度和高度
this.$toast('那個男人',{
position:'topCenter',
type:'success',
closeTime: 3 // 控制3秒後消失toast
autoClose: true,
callback () {
...
},
width:300,
height:80
})
複製程式碼
至此,基礎功能應該都涵蓋了,這個時候你要去考慮一些內建的問題
- 這麼多配置項,我作為一個使用者,都關心嗎?或者說,都需要配置嗎?
- 針對不同的狀態(success/error/warning/info),肯定要用不同的顏色區分,以及使用不同的圖示,他們之間有什麼關係嗎?
配置項多應該怎麼解決-預設值
預設給個type唄,比如我的專案中預設的type是info,當我在使用的時候,沒有傳入type時,預設為info
因為大部分的toast場景都是短暫的停留在頁面,所以autoClose設定為true
又因為大部分的toast文案比較短,所以我的預設toast長寬設定為300、80應該足夠了
...
以上預設配置,都可以在使用的時候,傳入引數覆蓋預設引數
針對不同的狀態,toast圖示、顏色、標題之間有什麼聯絡?
本地存一個map對映配置表,根據傳入的type,我就可以準確的知道圖示、顏色、標題應該是什麼
總結幾點:
- 外掛對外暴露的引數應保持最少原則,聚焦使用者關注點
- 外掛或元件的實現應該要基於使用場景考慮
- 開發一款元件或者外掛,應該保持軟體工程領域的開放封閉原則
- 一款好的外掛或元件並不是一蹴而就的,往往需要後期使用過程中發現問題,加以完善
- 元件或者外掛的文件一定要完善,並不是每一個使用它的人,都關心它的內部實現,他們更關心的可能僅是如何快速上手
實現
上文提到過,元件可以暴露資料給外掛,對於這句話
我的理解是,元件是靜態的,只是對外暴露一些引數入口props
。
外掛,讓我們可以動態的往其中注入一些自定義引數。具體的實現,還是在元件當中完成。
於是乎:我寫了一個靜態元件,通過props定義上文提到的相關變數
先看下script部分
再來看下html部分
可以看到,內部實現其實很簡單,無非就是通過外部傳入的props,控制內部的展示細節而已
到這裡靜態元件基本已經完成了(css樣式程式碼不在這裡貼了)
注意:
- props定義的時候,最好用物件的寫法,作為一定的約束
- 變數名字最好做到見名知意
- class名的繫結可以充分利用vue提供的陣列以及物件形式或者配合計算屬性完成
靜態元件怎麼變成外掛使用呢?
這裡不再做過多闡述,vue封裝外掛的常用方法主要有以下四種,有疑惑的話,建議觀閱vue開發外掛,當然我覺得你應該還需要去了解下Vue.extend的用法,外掛的實現離不開它哦。
看下關鍵部分:該檔案也是我們後期webpack打包(build)的入口檔案
該檔案內容涉及到的知識點,也是開發一個vue外掛最核心的內容。裡面的每一行程式碼,都充滿了殺機~
至此,關於外掛實現部分基本已經全部完成。
3.如何將自己的外掛上傳到npm上去
這裡的話,網上的教程有很多,我理解你只需要瞭解以下幾行程式碼的作用,就足夠了
// webpack.config.js
module.exports = {
entry: process.env.NODE_ENV === 'development' ? './src/main.js' : './src/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js',
libraryTarget: 'umd'
},
...
// package.json
{
"name": "mbs-toast",
"description": "a toast plugin base on Vue2",
"version": "1.0.0",
"author": "xxx <xxx88888@163.com>",
"license": "MIT",
"private": false,
"main": "dist/build.js",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
...
複製程式碼
- 這裡的entry入口檔案配置的意思是,開發環境時,入口檔案用main.js(方便開發除錯使用),打包時入口檔案為index.js
- filename是打包生成檔案的名字,這裡是webpack-simple模版預設使用的就是build.js,沒有特殊需求的話,不建議改動
- libraryTarget屬性可能大家都會比較陌生,因為一般如果只在專案中使用 webpack 不需要關注這兩個屬性,但是如果是開發類庫、外掛,那麼這兩個屬性就是必須瞭解的,不清楚的可以參考詳解webpack中ibraryTarget屬性
- package.json檔案中的main欄位,指定了該npm包引用的入口(記住一定要記得新增,並且檔名應與上面第二點提到的保持一致)
這裡我用的模版是自己在官方webpack-simple模版的基礎上做了一些定製化的,裡面為了方便我平時開發,加入了scss、eslint,這樣的話,後面就不用每次手動install了,有興趣的可以看下README,定製一份屬於自己的腳手架模板
在你瞭解了上述背景後,你只需要執行以下幾步即可實現皆大歡喜
順利的話,現在你已經可以在正式專案中,通過
npm install -S xxx 安裝你的私有包了
複製程式碼
最後在你的入口檔案註冊你的外掛
import toastPlugin from 'xxx'
Vue.use(toastPlugin) // 這裡Vue.use的第二個引數,可以通過全域性配置,做一些自定義配置,有需要的自行前往學習
複製程式碼
到這裡,所有的一切,已塵埃落定
你可以在程式碼中愉快的使用了
this.$toast('塵埃落定', {
callback () {
console.log('hello world')
},
type: 'success',
// position: 'topRight',
autoClose: false
})
複製程式碼
最後
我在寫這個外掛之前,在Github上看到一個大神封裝的外掛。四個字描述下,歎為觀止,有興趣的一定要去看下,我相信愛學習的你,一定會收穫滿滿。同時在開發該外掛時,一些樣式及動畫,也做了相應的參考。
該外掛的原始碼已經上傳mbs-toast,方便大家參考。同時,上述提到的form表單生成器,我也嘗試著自己實現了一遍,有興趣的可以一起加入哦。所有的外掛以及元件目前都彙總在麻不燒的Github裡,文件和README正在不斷完善中~
理科生畢業,文筆不好,勿噴~
碼字不易,且行且珍惜!