封裝vue外掛,讀懂這遍文章就夠了

麻不燒發表於2019-11-07

DEMO

麻不燒的Github

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
    })
複製程式碼

至此,基礎功能應該都涵蓋了,這個時候你要去考慮一些內建的問題

  1. 這麼多配置項,我作為一個使用者,都關心嗎?或者說,都需要配置嗎?
  2. 針對不同的狀態(success/error/warning/info),肯定要用不同的顏色區分,以及使用不同的圖示,他們之間有什麼關係嗎?
配置項多應該怎麼解決-預設值

預設給個type唄,比如我的專案中預設的type是info,當我在使用的時候,沒有傳入type時,預設為info

因為大部分的toast場景都是短暫的停留在頁面,所以autoClose設定為true

又因為大部分的toast文案比較短,所以我的預設toast長寬設定為300、80應該足夠了

...

以上預設配置,都可以在使用的時候,傳入引數覆蓋預設引數

針對不同的狀態,toast圖示、顏色、標題之間有什麼聯絡?

本地存一個map對映配置表,根據傳入的type,我就可以準確的知道圖示、顏色、標題應該是什麼

map

總結幾點:

  • 外掛對外暴露的引數應保持最少原則,聚焦使用者關注點
  • 外掛或元件的實現應該要基於使用場景考慮
  • 開發一款元件或者外掛,應該保持軟體工程領域的開放封閉原則
  • 一款好的外掛或元件並不是一蹴而就的,往往需要後期使用過程中發現問題,加以完善
  • 元件或者外掛的文件一定要完善,並不是每一個使用它的人,都關心它的內部實現,他們更關心的可能僅是如何快速上手
實現

上文提到過,元件可以暴露資料給外掛,對於這句話

我的理解是,元件是靜態的,只是對外暴露一些引數入口props。 外掛,讓我們可以動態的往其中注入一些自定義引數。具體的實現,還是在元件當中完成。

於是乎:我寫了一個靜態元件,通過props定義上文提到的相關變數

先看下script部分

script

再來看下html部分

html

可以看到,內部實現其實很簡單,無非就是通過外部傳入的props,控制內部的展示細節而已

到這裡靜態元件基本已經完成了(css樣式程式碼不在這裡貼了)

注意:

  • props定義的時候,最好用物件的寫法,作為一定的約束
  • 變數名字最好做到見名知意
  • class名的繫結可以充分利用vue提供的陣列以及物件形式或者配合計算屬性完成

靜態元件怎麼變成外掛使用呢?

這裡不再做過多闡述,vue封裝外掛的常用方法主要有以下四種,有疑惑的話,建議觀閱vue開發外掛當然我覺得你應該還需要去了解下Vue.extend的用法,外掛的實現離不開它哦。

看下關鍵部分:該檔案也是我們後期webpack打包(build)的入口檔案

config

該檔案內容涉及到的知識點,也是開發一個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,定製一份屬於自己的腳手架模板

在你瞭解了上述背景後,你只需要執行以下幾步即可實現皆大歡喜

steps

順利的話,現在你已經可以在正式專案中,通過

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正在不斷完善中~

理科生畢業,文筆不好,勿噴~

碼字不易,且行且珍惜!

相關文章