前言
很多時候面對日常的工作業(yè)務需求,或者面對新項目時往往都是npm i element-ui -S安裝element或者Ant的組件庫,但如果自己想要面對特殊的需求需要定制組件往往需要不斷修改,改完又往往忘記了整理,最后就是不斷的重復。
你所寫的每一個 vue 文件都可以視為一個組件,隨著業(yè)務的不斷深入,頁面寫多了想將組件集合起來封裝成一個組件庫的想法也不斷加劇。僅在此寫下組件庫的構建思路和歷程,供自己記憶學習,也希望能幫助到你。
目錄構建
推薦使用@vue/cli 進行項目的構建
npm install -g @vue/cli-
命令行中輸入
vue reate orange_collect快速初始化一個項目。
image 將src的目錄文件改為examples,用來寫組件相關文檔和事例。
再新建一個src目錄,里面只放一個main.js用來作為打包入口
在根目錄下新建一個 packages 文件夾,用來進行組件的編寫。
-
在根目錄下新建一個vue.config.js文件,配置如下
const NODE_ENV = 'development' // 開發(fā)環(huán)境 打包doc // const NODE_ENV = 'lib' // 組件庫 上傳npm const components = require('./build/compontents.json'); const path = require('path') const baseConfig = { chainWebpack: config => { config.resolve.alias .set('@', path.resolve('examples')) .set('~', path.resolve('packages')) config.module .rule('js') .include .add('/packages') .end() .use('babel') .loader('babel-loader') .tap(options => { // 修改它的選項... return options }) }, //如有scss配置需求 // css: { // extract: false, // loaderOptions: { // // 給 sass-loader 傳遞選項 // sass: { // data: `@import "public/css/ui.scss";` // } // }, // } } const devConfig = { pages: { index: { entry: 'examples/main.js', template: 'public/index.html', filename: 'index.html', } }, publicPath: './', outputDir: 'docs', ...baseConfig } const buildConfig = { configureWebpack: { entry: components, output: { filename: '[name].js', libraryTarget: 'commonjs2', }, }, outputDir: 'lib', productionSourceMap: false, ...baseConfig } module.exports = NODE_ENV === 'development' ? devConfig : buildConfig;
這里通過判斷NODE_ENV來判斷項目的打包方式,在development下把examples 加入編譯,將examples/main.js設置為文件入口。設置examples和packages的別名。
此時運行npm run serve已可以正常啟動項目。將HelloWorld頁面稍作修改,添加樣式和布局。
- 在
router中添加頁面路由import Vue from 'vue' import Router from 'vue-router' import Home from '../components/HelloWorld.vue' //組件 import component from './component' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'home', component: Home, redirect: '/component/installation', children: [ //組件 ...component, ] }, ] })image
相關界面如上,需要樣式和布局代碼可以去我的github上查看,再次不在贅述。
組件編寫
常規(guī)組件編寫
- 我們組件的編寫都在packages文件夾中進行,舉個??(例子),現編寫一個測試的button組件。
├─packages │ └─orange_btn #組件模塊名稱文件夾 │ ├─src │ | ├─orange_btn.vue │ └─index ├─index.js - 新建一個如上的目錄結構,接下來我們就需要在
orange_btn.vue中編寫相關的業(yè)務代碼。通過props來定義組件的相關組件和狀態(tài)擴展。export default { props: { type: { type: String, default: "default" }, size: String, icon: { type: String, default: "" } }, name: "orange-button", data() { return {}; }, - 值得注意的是在orange_btn.vue中
name屬性尤為重要它是必須要寫的,是判斷是否唯一組件的標識,所以你寫的應該是不重名的。之后name將用來判定組件,如這里的name是orange-button在之后完
成組件的注冊并且最終使用的時候則是<orange-button></orange-button>
組件圖標的引入和使用
- 建議使用iconfont矢量圖庫將ui的圖標上傳,或在圖標庫中尋找合適的圖標后,下載至本地。
-
將圖中的字體文件夾引入項目
image - 在packages文件夾的
index.js和examples的main.js中對字體文件進行引入import './assets/font/iconfont.css' - 使用
iconfont+類名<i class="iconfont xxxx"/>
組件暴露
-
每一個組件都需要如此步驟,先建立組件同名的文件夾,然后在
orange_btn文件夾下的index·js下編寫暴露代碼,用于安裝單個組件import BlackBtn from './src/orange_btn.vue' // 為組件提供 install 安裝方法,供按需引入 BlackBtn.install = function (Vue) { Vue.component(BlackBtn.name, BlackBtn) } // 默認導出組件 export default BlackBtn -
在packages文件夾下新建一個
index.js用來管理,可以避免我們的組件越來越多,需要重復引入,循環(huán)安裝所有組件。import orange_btn from './orange_btn' // 存儲組件列表 const components = [ orange_btn ] // 定義 install 方法,接收 Vue 作為參數。如果使用 use 注冊插件,則所有的組件都將被注冊 const install = function (Vue) { // 判斷是否安裝 if (install.installed) return // 遍歷注冊全局組件 components.map(component => Vue.component(component.name, component)) } // 判斷是否是直接引入文件 if (typeof window !== 'undefined' && window.Vue) { install(window.Vue) } export default { // 導出的對象必須具有 install,才能被 Vue.use() 方法安裝 install, // 以下是具體的組件列表 orange_btn }
組件引入
-
在examples用來寫組件相關文檔和事例。在examples的
main.js中引入
image -
使用
<orange-button></orange-button>已可以在頁面中使用,由此可以編寫相關的文檔說明。
image
打包配置
- 在項目組件編寫過后,就可以將組件打包??上傳至npm使用
- 將
vue.config.js下的NODE_ENV改為lib模式 - 新建build文件夾,寫一個方法
const fs = require('fs-extra'); const path = require('path'); function isDir(dir) { return fs.lstatSync(dir).isDirectory(); } function transformStr3(str) { var re = /-(\w)/g; return str.replace(re, function ($0, $1) { return $1.toUpperCase(); }); } // function firstUpperCase(str) { // return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase()); // } const json = {}; const dir = path.join(__dirname, '../packages'); const files = fs.readdirSync(dir); files.forEach(file => { const absolutePath = path.join(dir, file); if (isDir(absolutePath)) { let fileKey = transformStr3(file.replace('orange_', '')) // console.log(fileKey) json[fileKey] = `/Users/chenzhikun/project/GitHub/orange_ui/packages/${file}/index.js`; //mac // json[fileKey] = `D:/projects/orange_ui/packages/${file}/index.js`; //windows } }); - 通過運行方法,獲得組件的路徑之后在
vue.config.js中引入const components = require('./build/compontents.json') - 運行
npm run build可以得到一個lib文件,這個文件就是我們最終要上傳到npm的文件。此時文件目錄如下。
npm發(fā)布
-
npm發(fā)布時,要將package.json中的private屬性值改為false并修改項目的版本號
image - 我們沒有必要把所有的代碼都發(fā)布到npm上。在項目的根目錄創(chuàng)建一個.npmignore的文件,對多余的文件進行忽略.
.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* # 以下是新增的 # 要忽略目錄和指定文件 build/ examples/ packages/ public/ src/ util/ vue.config.js babel.config.js *.map *.html - 執(zhí)行
npm who am i命令, 如果沒有登陸則執(zhí)行npm login命令,系統會提示輸入賬戶和密碼。如果沒有則需要前往npm官網進行注冊。 - 登陸之后執(zhí)行
npm publish進行版本發(fā)布。 - 在npm發(fā)布完成之后就可以在任意一項目中使用
npm i orange_collect來安裝項目,之后在main.js中引入import orange from 'orange_collect' import 'orange_collect/lib/orange_collect.css' Vue.use(orange)
此時的組件均能通過標簽正常的使用。
小結
從零新建一個自己的組件庫至此就已經完成了,如果想我一樣團隊中有需要封裝自己的組件代碼庫,則可以試著像我一樣寫一個輪子一起用,我則是想收集各類有意思的按鈕進行自己的封裝。github地址