基於 vue-cli3 打造屬於自己的 UI 庫

尤水就下也發表於2019-03-28

寫在前面

小小的前端有大大的夢想。做一個屬於我們自己的 UI 元件庫應該是個不錯的小目標了。那。。。元件是什麼??我想應該不用多說,在日常開發中我們天天與之打交道,你所寫的每一個 vue 檔案都可以當做是一個元件,只不過通用性有所區別而已。元件寫得多了,隨著時間的推移,你就會有寫一個元件庫的衝動了。其實更多的為了提升 B 格?,當和別人談論的時候,你說你寫過一個 UI 庫,別人就覺得你可能有點吊。好了,不吹 B,趕緊擼吧?

原始碼地址:github.com/lgq627628/x…

知識前置

我們可能習慣了在一個 vue 裡面引入元件的方式,所以先這裡要鞏固一下全域性引入元件的方式。舉個栗子?,一般我們的用法是這樣的:

import Loading from '../components/loading'
// 方法一:name 是元件的名字
Vue.component(Loading.name, Loading)
// 方法二:前提是 Loading 有提供 install 這個方法
Vue.use(Loading);
複製程式碼

上面兩種方式都可以用來全域性註冊元件,但是引數不一樣,選擇哪種方法都可以,但要留意一下第二種方法,這種方法需要元件本身有個 install 的方法。額。。。為啥要有 install 的方法?這個你就當做是規定就好,你用人家的框架就得遵循人家的規則。扯犢子吧?,其實是因為執行 Vue.use 的時候會執行裡面的 install 方法,所以我們需要寫個 install。對此你不用較真,寄人籬下是這樣的,哦不對?‍♀️,應該是站在大神的肩膀上?。

搭建目錄

快速建立專案

這步應該不用多說吧,執行一下 vue create xr-ui(前提是你安裝了 vue-cli3),然後看自己喜好選擇一些配置,幾下回車之後一個清爽的初始專案就有了。這裡我沒有選擇用 typescript(主要是我還沒習慣用它),所以選用 typescript 的同學們注意啦,可能寫法會有少許不同,有勞大夥看著改下吧。

修改目錄結構

  1. 把 src 目錄名字改成 examples,這是用於展示元件示例的
  2. 在根目錄下新建一個 packages 資料夾,這是用來放元件的
    基於 vue-cli3 打造屬於自己的 UI 庫
    你可能會問為什麼要建這樣的目錄結構,問得好,原因很簡單,因為別人是這樣做的,所以借鑑(模仿)羅。。。我們可以看到 Element 的原始碼也是這樣的結構:
    基於 vue-cli3 打造屬於自己的 UI 庫

當我們水平不夠的時候,模仿是一種強大的學習能力?。

新增配置檔案

小改了一下目錄之後,你會驚奇的發現專案執行不了了。沒關係,這很正常,畢竟 src 都不見了,路徑啥的肯定得報錯。所以現在我們來解決這個問題。 在根目錄下新建一個 vue.config.js 檔案(新專案是沒有這個檔案的),並寫入以下內容:

const path = require('path')
module.exports = {
  // 修改 pages 入口
  pages: {
    index: {
      entry: 'examples/main.js', // 入口
      template: 'public/index.html', // 模板
      filename: 'index.html' // 輸出檔案
    }
  },
  // 擴充套件 webpack 配置
  chainWebpack: config => {
    // @ 預設指向 src 目錄,這裡要改成 examples
    // 另外也可以新增一個 ~ 指向 packages
    config.resolve.alias
      .set('@', path.resolve('examples'))
      .set('~', path.resolve('packages'))

    // 把 packages 和 examples 加入編譯,因為新增的檔案預設是不被 webpack 處理的
    config.module
      .rule('js')
      .include.add(/packages/).end()
      .include.add(/examples/).end()
      .use('babel')
      .loader('babel-loader')
      .tap(options => {
        // 修改它的選項...
        return options
      })
  }
}
複製程式碼

上面的註釋應該都寫的挺明瞭,主要就是修改別名、修改入口檔案以及把新檔案加入 webpack 編譯這幾個步驟。然後我們再執行一下程式就可以跑得通了。至於為什麼這麼配置、或者怎麼配置,不瞭解的同學可以去 Vue Cli 官網看下,上面寫的是清清楚楚、明明白白,然而我也只是懂那麼一兩個配置而已???,還沒學會 webpack 的套路,因為常常是用的時候看一眼,一陣子不用就又忘了,沒辦法?‍♀️腦子不行。

編寫元件

一個元件庫沒有元件怎麼行呢,所以我們要先寫個 test 元件(你可以隨便寫,這不重要)。ok?,我們先在 packages 目錄下新建一個 test 資料夾,再在 test 資料夾下下面新建一個 src 資料夾,在 src 資料夾下面新建一個 test.vue 元件,大概長下面這樣子?:

基於 vue-cli3 打造屬於自己的 UI 庫

<!--test.vue-->
<template>
  <div class="xr-test" @click="handleClick">{{ num }}</div>
</template>

<script>
export default {
  name: 'XrTest', // 這個名字很重要,它就是未來的標籤名<xr-test></xr-test>,坑了我一下
  data () {
    return {
      num: 0
    }
  },
  methods: {
    handleClick () {
      this.num++
    }
  }
}
</script>

<style lang="scss" scoped>
.xr-test {
  width: 100px;
  height: 100px;
  line-height: 100px;
  border-radius: 50%;
  font-size: 30px;
  text-align: center;
  background: #24292e;
  color: white;
}
</style>
複製程式碼

應該都能看懂吧,不過多解釋。⚠️這裡主要強調一點,就是 name 這個名字尤為重要,我就在這個坑裡呆了挺久。首先它是必須要寫的,為啥呢,你可以把它理解為 id,具有唯一標識元件的作用,將來我們可是要通過這個 name 來找到和判定這是什麼元件,所以你寫的所有元件應該是不重名的;其次這個 name 就是我們最終的標籤名,比如這裡我們的 name 是 XrTest,到時候我們寫的標籤就長這樣 <xr-test></xr-test>,就像 Element 一樣,name 是 ElButton,用的時候就是 <el-button></el-button>

暴露元件

讓我們在 packages/test 下面新建一個 index.js 檔案,具體程式碼如下:

// 為元件提供 install 方法,供元件對外按需引入
import XrTest from './src/test'
XrTest.install = Vue => {
  Vue.component(XrTest.name, XrTest)
}
export default XrTest
複製程式碼

這步的精髓就在於給元件擴充套件一個 install 方法,至於為什麼要擴充套件這個方法,文章開頭已經說到了,是因為 Vue.use() 的需要,use 會預設呼叫 install 方法安裝,僅此而已。接著我們在 packages 下面也新建一個 index.js 檔案,注意和上面那個 index.js 區別開,上面那個是針對單個元件安裝的,這個是針對所有元件全域性安裝的,先看程式碼:

import XrTest from './test'
// 所有元件列表
const components = [
  XrTest
]
// 定義 install 方法,接收 Vue 作為引數
const install = function (Vue) {
  // 判斷是否安裝,安裝過就不繼續往下執行
  if (install.installed) return
  install.installed = true
  // 遍歷註冊所有元件
  components.map(component => Vue.component(component.name, component))
  // 下面這個寫法也可以
  // components.map(component => Vue.use(component))
}

// 檢測到 Vue 才執行,畢竟我們是基於 Vue 的
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

export default {
  install,
  // 所有元件,必須具有 install,才能使用 Vue.use()
  ...components
}
複製程式碼

這步的主要作用就是統一匯出所有元件及暴露 install 方法。之前的 index.js 只是安裝單個元件,而現在這個 index.js 是迴圈安裝所有元件,具體使用就看你是不是要按需引用了。這裡給個目錄結構方便大家觀看:

基於 vue-cli3 打造屬於自己的 UI 庫
因為這步挺重要的,所以建議好好停下來理解消化一下?。。。
當然你可能會問道,為什麼這樣建目錄?還能什麼原因,因為 Element 是這樣(如下圖),所以我們這樣寫,僅此而已。
基於 vue-cli3 打造屬於自己的 UI 庫

元件測試

ok,元件寫完了,接下來我們就在 examples 下面測試一下,看看能不能引用成功。 首先在 examples 下的 main.js 中引入剛剛寫好的包,就像下面這樣:

基於 vue-cli3 打造屬於自己的 UI 庫
然後把 examples/views 下面的 Home.vue 裡面的內容刪了,寫入自己標籤元件,就像下面這樣:
基於 vue-cli3 打造屬於自己的 UI 庫
好了,最後讓我們執行一下專案 yarn serve,看看效果,嗯,還湊合吧。

庫模式打包

在 vue-cli3 中我們通過以下命令可以將一個單獨的入口打包成一個庫:

// target: 預設為構建應用,改為 lib 即可啟用構建庫模式
// name: 輸出檔名
// dest: 輸出目錄,預設為 dist,這裡我們改為 lib
// entry: 入口檔案路徑
vue-cli-service build --target lib --name lib [entry]
複製程式碼

要注意的是在庫模式中,打包出來的庫中是不包含 Vue 的。 然後我們修改一下 package.json 檔案,就像下面這樣:

基於 vue-cli3 打造屬於自己的 UI 庫
接著執行 npm run lib 就能生成庫啦,看看左側的目錄是不是多了個 lib 資料夾,那個就是我們要釋出的東西。
基於 vue-cli3 打造屬於自己的 UI 庫
基於 vue-cli3 打造屬於自己的 UI 庫
補充下,lib 目錄下面的 js 之所以有好幾種,是因為有兩種規範(common 和 umd)、是否壓縮(min)和對映(map)的區別,暫且知道有這麼回事就行,不用深究。

釋出到npm

萬事俱備,只欠釋出。

  1. 完善一下 README.md 文件,這個隨便寫兩句就好
  2. 修改一下 package.json 檔案:
{ 
  "name": "xr-ui",
  "version": "0.3.0",
  "description": "基於 vue-cli3 的 UI 元件庫",
  "main": "lib/xr-ui.umd.min.js",  // 這是 lib 目錄下的其中一個
  "keywords": "xr-ui",
  "private": false,
  "license": "MIT"
}
複製程式碼
  1. 在根目錄下新建一個 .npmignore 檔案,內容和 .gitignore 差不多:
# 這是複製 .gitignore 裡面的
.DS_Store
node_modules
/dist

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

# 以下是新增的
# 要忽略目錄和指定檔案
examples/
packages/
public/
vue.config.js
babel.config.js
*.map
*.html
複製程式碼

最後執行 npm login 登入 npm 賬號,再執行 npm publish 釋出即可,就這麼簡單的兩步就可以,過一會在 npm 上就能搜到了。當然前提是你有個 npm 賬號,沒有的話去註冊一個吧,很 easy 的,然後還要搜下你的 npm 包名是否有人用,有的話就換一個。

小試牛刀

終於,歷盡千辛萬苦,我們可以引用自己寫的庫拉,想想就牛叉。別激動,讓我們試驗一下,用 vue create new 另起一個新專案,然後 npm i xr-ui -S,可以在 node_modules 裡面看到我們的包大概長這樣:

基於 vue-cli3 打造屬於自己的 UI 庫
然後在 main.js 引入:

import Vue from "vue"
import XrUI from 'xr-ui'
import 'xr-ui/lib/xr-ui.css'

Vue.use(XrUI)
複製程式碼

這樣我們就能在頁面中引入元件啦,哈哈哈哈,賊開心,喜上眉梢。。。

<xr-test></xr-test>
複製程式碼

小結

想想如果你為團隊維護一個元件庫,那是多麼牛叉的事情。當然,好記性不如爛鍵盤,看懂並不代表掌握,只有自己體驗過才是真的難忘,?額。。怎麼突然抒情了起來。
最後還是強調一點吧,水平不夠的時候,模仿是一種必備的技能,就像我。不過沒關係,這只是個過程,當你寫了幾年的程式碼後,總會有一些自己的想法,然後也能慢慢沉澱出一些屬於自己的東西,我們只是站在巨人的肩膀上前行,僅此而已,回見???

相關文章