基於Vue的npm組件庫

前言(*❦ω❦)

思維導圖可能有點高糊,有點太大了,項目和導圖文件放到githubgiteee上,這個思維導圖也是我文章的架構,思維導圖是用FeHelper插件生成的,這個是一款開源chrome插件,訪問地址按照插件項目說明安裝即可,然後導入我的思維導圖的JSON文件即可,JSON文件會放在項目中。
思維導圖


構建vue npm 組件庫需要準備的事(會的同學可跳過)( ゚▽゚)/

  這裡主要講一下搭建一個vue組件庫需要事先準備的條件,其實也是一個合格的初級前端開發人員的必備條件。

  • 編輯器工具: VsCode下載地址
      首先是使用工具,個人推薦VsCode,因為感覺前端用這款軟體太合適不過了,各種插件用得好完全可以起飛。

  • git環境: git安裝可以網上查查資料,安裝好邊學邊用就可以了,協同開發工具能用就可,需要深入再學不遲,只要了解分支開發等等基礎內容就行了。然後配合github這個著名的交友網站(手動滑稽)就可以了,主要是用來保存自己的組件庫程式碼,搭建組件庫暫時還用不到,本地保存主要怕丟失了,所以雲備份一份萬無一失。

  • Node.js環境: 不會吧!不會吧!不會有人學前端還不知道Node.js吧, 好吧!其實我剛開始學也是不知道的,後面也是慢慢接觸到,菜到自閉⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄,安裝node環境主要是用npm包管理工具,npm真是前端人的靈魂。Node.js下載地址,安裝相關可以參考這篇部落格。安裝完成後推薦安裝nrm這個包,主要是用它換源賊方便,這裡建議看看這篇部落格(理直氣壯夾帶私貨(。-`ω´-))。下圖是我的node版本和npm版本:
      node版本

  • vue&vue-cli: Vue是前端一個漸進式框架,vue-cli是一個項目構建工具,這裡主要是用cli來構建一個基礎的組件庫項目,具體的細節就不做過多解釋了。

  • 註冊npm一個帳號: npm官網,註冊帳號就不用多說了吧,準備好一個郵箱,然後註冊的時候記著註冊名和密碼,後面發布npm包會使用到。

  • 小小建議: 公司讓我嘗試搭建一個公用的組件庫,主要是前端一些程式碼復用率高,能抽成組件可以減少冗餘,剛開始也是一臉迷茫,翻閱不少部落格後才完成基本的搭建流程,期間也有看過element源碼,當然不可能是完全啃源碼,主要是餓了么這麼優秀的vue開源ui組件庫不看看源碼,怎麼對得起天天使用它٩(๑❛ᴗ❛๑)۶。主要是借鑒一下,整個項目的文件構建結構,然後組件構建的流程,大致能順一下流程。最後再搭建組件庫的過程中也確實對我有一定的幫助,所以建議大家也看看源碼。(o°ω°o)

開始搭建組件庫ヾ(≧∇≦*)ヾ

創建項目&調整文件名

查看vue-cli版本

  搭建項目我使用的是 vue-cli的4+ 版本,node版本之前也有截圖,cli最好是用 3+版本 。完成這些後,找一個保存項目的文件夾,然後使用cmd輸入vue create xd-test-ui就可以創建名為xd-test-ui的項目了

vue-cli版本&創建

創建項目

  cmd輸入vue create xd-test-ui後會來到這個頁面,一路回車默認就可了,這裡我選擇vue2版本,剩下的是默認配置,是一些編譯和拼寫檢測的配置,直接默認即可,如果想要深入了解,可以學習學習webpack,這些配置完成後就進入安裝頁面,等待項目創建完成。

  • 配置選項
       vue項目構建

  • 安裝過程
       cli安裝過程

  • 項目創建完成
      可以看到構建完成後,最後提示使用npm run serve運行,這是基礎的vue-cli項目,當然這只是剛開始,完成組件庫還需要進行進一步的"脫胎換骨"┐( ̄ヮ ̄)┌。項目初始樣子完成後,使用VsCode從項目根目錄打開該項目。
      

調整文件夾命名

  看了很多的部落格,大家基本都是這個樣子來修改的,包括element源碼裡面的項目,也是有examples文件夾(項目示例文件夾)和packages文件夾(組件文件夾),所以這裡隨大流,將創建好的項目修改成如下的格式。

·
··
...
|-- examples      // 原 src 目錄,改成 examples 用作示例展示
|-- packages      // 新增 packages 用於編寫存放組件
...
··
·
  • 修改文件名前後(src->examples,新增 packages)
    修改前
    修改後

項目配置調整

完成上述修改後,項目無法運行,需要調整配置,在 根目錄 添加vue.config.js文件,配置程式碼如下,vue.config.jsvue-cli3新增提供的一個可選配置文件,相關的配置鏈式操作可以查看官網的這篇配置介紹 webpack-chain,完成這些配置後項目就可以重新運行了。

//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
            })
    }
}

編寫組件 φ(>ω<*)

組件目錄構建

構建如下的文件目錄格式,然後構建完成後就可以開始寫程式碼了

|——
|——packages
|   |——index.js
|   |——button
|      |——index.js
|      |——src
|         |——button.vue
|——

項目整體樣子
目前為止的目錄截圖。

組件程式碼編寫

  • button.vue文件內容

  這裡就是單個的組件文件,每個packages下的文件夾就是一個組件,這裡是基礎組件樣式的編寫。

<template>
  <div>
    <a :class="type">
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <slot></slot>
    </a>
  </div>
</template>

<script>
export default {
  name: "XdButton",
  props: {
    type: {
      type: String,
      default: "primary",
    },
  },
};
</script>

<style scoped>
@import url("//fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

a {
  position: relative;
  display: inline-block;
  padding: 25px 30px;
  margin: 40px 0;
  color: #03e9f4;
  text-decoration: none;
  text-transform: uppercase;
  transition: 0.5s;
  letter-spacing: 4px;
  overflow: hidden;
  margin-right: 50px;
}
a:hover {
  background: #03e9f4;
  color: #050801;
  box-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
    0 0 200px #03e9f4;
  -webkit-box-reflect: below 1px linear-gradient(transparent, #0005);
}

.warning {
  filter: hue-rotate(300deg);
}

.success {
  filter: hue-rotate(240deg);
}

a span {
  position: absolute;
  display: block;
}
a span:nth-child(1) {
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, transparent, #03e9f4);
  animation: animate1 1s linear infinite;
}
@keyframes animate1 {
  0% {
    left: -100%;
  }
  50%,
  100% {
    left: 100%;
  }
}
a span:nth-child(2) {
  top: -100%;
  right: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(180deg, transparent, #03e9f4);
  animation: animate2 1s linear infinite;
  animation-delay: 0.25s;
}
@keyframes animate2 {
  0% {
    top: -100%;
  }
  50%,
  100% {
    top: 100%;
  }
}
a span:nth-child(3) {
  bottom: 0;
  right: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(270deg, transparent, #03e9f4);
  animation: animate3 1s linear infinite;
  animation-delay: 0.5s;
}

@keyframes animate3 {
  0% {
    right: -100%;
  }
  50%,
  100% {
    right: 100%;
  }
}

a span:nth-child(4) {
  bottom: -100%;
  left: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(360deg, transparent, #03e9f4);
  animation: animate4 1s linear infinite;
  animation-delay: 0.75s;
}
@keyframes animate4 {
  0% {
    bottom: -100%;
  }
  50%,
  100% {
    bottom: 100%;
  }
}
</style>
  • button/index.js內容編寫

  如果要暴露組件,還需在組件文件夾內編寫向外暴露組件的js文件

// 導入組件,組件必須聲明 name
import Button from './src/button'

// 為組件提供 install 安裝方法,供按需引入
Button.install = (Vue) => {
    Vue.component(Button.name, Button)
}

// 默認導出組件
export default Button
  • packages/index.js文件編寫

  在這裡提供兩種組件註冊方式,一種是使用use全部引入,另一種是按需引入組件,使用方法和elemnet組件引用方法一樣。目前只寫了一種組件,所以兩種引入的都一樣。

import button from './button'
// 存儲組件列表
const components = [
    button
]
/* 
  定義install 方法,接收Vue作為參數,如果使用use註冊插件,則所有的組件都將被註冊
*/
const install = (Vue) => {
    // 判斷是否安裝
    if (install.installed) { return }
    // 遍歷所有組件
    components.map(item => {
        Vue.component(item.name, item)
    })
}

//判斷Vue初始化
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}

export default {
    install,
    button
}

在組件庫項目內引用組件(測試組件所用,可以跳過)

  在examples/main.js中全局註冊組件,然後在examples/components/HelloWorld.vue文件中編寫使用按鈕組件。

  • main.js文件內容如下
import Vue from 'vue'
import App from './App.vue'

import XdUi from '../packages/index' //組件庫項目內引入組件
Vue.use(XdUi); //全局註冊組件

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
  • 在HelloWorld.vue中的程式碼如下
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <XdButton>default</XdButton>
    <xd-button type="primary">primary</xd-button>
    <xd-button type="warning">warning</xd-button>
    <xd-button type="success">success</xd-button>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
};
</script>

這裡我只是刪除了一些組件庫項目的默認內容,然後在這個頁面中測試我編寫的組件,在項目內測試,以防上傳組件庫後發現錯誤再折騰回來修改。

  • 組件引用效果截圖

組件效果截圖

組件打包

package.json文件編寫

  • name: 包名,該名字是唯一的。可在 npm 官網搜索名字,如果存在則需換個名字。
  • version: 版本號,每次發布至 npm 需要修改版本號,不能和歷史版本號相同。
  • description: 描述。
  • main: 入口文件,該欄位需指向我們最終編譯後的包文件。
  • keyword:關鍵字,以空格分離希望用戶最終搜索的詞。
  • author:作者
  • private:是否私有,需要修改為 false 才能發布到 npm
  • license: 開源協議
    以下為參考設置
···
  "description": "基於Vue搭建的一個基礎組件庫。",
  "main": "lib/xd-ui.umd.min.js",
  "private": false,
  "license": "MIT",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "lib": "vue-cli-service build --target lib --name xd-test-ui --dest lib packages/index.js"
  },
···
  1. 編譯為庫的命令 lib 內容解析

    • vue-cli-service build 構建包的命令
    • –target: 構建目標,默認為應用模式。這裡修改為 lib 啟用庫模式。
    • –name:指定編譯後的組件文件名字。
    • –dest : 輸出目錄,修改為lib。
    • 最後一個參數為入口文件,默認為 src/App.vue。這裡我們指定編譯 packages/ 組件庫目錄。
  2. 打包後圖示說明
    打包圖示

打包命令:npm run lib

上傳到npm官網 罒ω罒

  終於到了「雞凍」人心的一步了,發布正式的npm包,然而到這裡還需要在發布前做一些準備工作。

  1. 添加.npmignore文件

  上傳到npm當然只需要一個構建好的lib和相關的幾個文件就足夠了,這樣別人引入的時候體積小,也不用獲取多餘的文件,就像上傳到github不需要node_modules文件夾一樣,因為這些東西太大,而且沒有必要上傳,所以這裡在根目錄添加.npmignore文件,在裡面寫入忽略上傳的文件夾和文件即可。

以下是參考配置:

# 這是複製 .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
  1. 登錄到npm
    • 首先需要到 npm 上註冊一個帳號,注意驗證郵箱,不然之後會發布不了。
    • 如果配置了淘寶鏡像,先設置回npm鏡像。
      • 在控台輸入 npm config set registry //registry.npmjs.org 切換源
      • 或者使用 nrm use npm 當然需要安裝NRM,前面說過了。
    • 然後使用 npm login 登錄,輸入之前註冊的資訊。
      登錄npm
    • 最後使用 npm publish 發布包,好耶!ヽ(゚∀゚)メ(゚∀゚)ノ 終於發布了第一個自己的包了。可以看到包的版本是0.1.0,後續再發布包需要修改成和歷史不同的版本號。如果發布成功,npm會使用郵件通知你,可以在郵箱中查看到自己的發布包成功的消息。
      發布npm包
    • 登錄到npm官網查看自己發布的包
      npm官網查看發布的包

到這一步我們就完成了整個基於vue的npm包發布的流程,完成了第一個組件庫的搭建,如果你成功了,哦耶!恭喜你!!!如果沒有成功可能是版本或者某些配置遺漏了,可以回過頭去看看,或者 重新來一次ヽ(・ω・´メ)(不要打我)。到這裡基本就完成了組件庫的搭建,好累啊啊啊!!!

新建項目引入安裝自己的npm包測試 ❥(ゝω・✿ฺ)

當然如果要完成整個流程,那肯定得新建項目測試一下自己的包是否能用。

  1. 構建新的項目 vue create 項目名

  2. 使用 npm i xd-test-ui 安裝上傳的npm包。
    上傳的包安裝

  3. 確認檢查包是否安裝了。

    確認包引入

  4. 在新項目中掛載下載好的組件。

import XdUi from "xd-test-ui" //引入組件
import "xd-test-ui/lib/xd-test-ui.css" //之前在組件庫項目中沒有引入,因為是一個項目,而新項目需要引入css文件才會有樣式。
Vue.use(XdUi); //全局註冊組件
  1. 在頁面內編寫引入的組件
<XdButton>默認</XdButton>
<xd-button type="primary">指定默認樣式</xd-button>
<xd-button type="warning">警告樣式</xd-button>
<xd-button type="success">成功樣式</xd-button>
  1. 效果展示
    成功
    警告
    默認

好了,這裡就萬無一失的確認組件ok,引入沒有問題,npm組件庫完全的完成了,可喜可賀,可喜可賀!\\\٩(‘ω’)و////

項目地址✧⁺⸜(●˙▾˙●)⸝⁺✧

npm包地址

項目地址

在項目中使用 npm i xd-test-ui 引入,然後和上述的方法一樣引入即可。

github倉庫地址

項目地址

使用git clone //github.com/ZERO-DG/xd-test-ui.git下載項目。求個Star

gitee倉庫地址

項目地址

使用git clone //gitee.com/zero-dg/xd-test-ui.git下載項目。

參考大佬的部落格

大佬0001

大佬0002

大佬0003

大佬0004

以上大佬部分先後順序,本部落格有部分借鑒的地方,全部來自於以上部落格,感謝各位大佬!

Tags: