在開發組件時,咱們可能會指望一類組件放在同一個代碼倉庫下,就像element
那樣,咱們可使用element
提供的腳手架,也可使用vue cli 3
建立一個更‘新’的項目。javascript
經過vue cli 3
建立項目,建立文件夾packages
用於存放組件。html
在packages
下就是每個組件,每一個組件和單獨項目同樣,會有package.json
、README.md
、src
、dist
等文件及目錄。vue
在組件開發過稱中,咱們須要對組件進行展現,因此建立了examples
文件夾,用於存放每一個組件示例。
經過一個列表展現出全部的組件,點擊選擇當前開發的組件,進入對應的example
。
路由的根就是一個導航列表,而後每一個組件對應一個路由,經過一個配置文件的components.js
來生成這個路由。java
// 路由
import Navigation from "./Navigation";
import components from "./components";
let routes = components.map(component => ({
path: `/${component.name}`,
component: () => import(`../examples/${component.name}`)
}));
routes.unshift({
path: "",
component: Navigation
});
export default routes;
複製代碼
建立新的組件,須要修改components.js
配置文件,在examples
和packages
下建立對應目錄。
編譯/發佈組件,由於倉庫下會有多個組件,若是一次發佈多個,就須要進入每一個文件夾下執行命令。
上面過程實現自動化,有不少種方式,好比能夠經過npm run <script>
,能夠直接經過node
命令等。這裏我參考element
,採用了Makefile。node
建立script
文件夾,其中包括建立腳本new.js
和構建腳本build.js
。npm
建立腳本主要就是目錄的建立與文件的寫入,其中可能須要注意的可能就是格式問題。
一種方式是在``之間,按照規範格式去完成寫入內容,這樣作比較麻煩,並且可能面臨格式化要求修改問題。
另外一種方式是在腳本中引入eslint
,腳本中的eslint.CLIEngine
能夠根據配置文件(好比.eslintrc.js
)格式化文件。須要注意的是須要比命令行中配置須要多添加fix: true
配置, 以下json
const CLIEngine = eslint.CLIEngine;
const cli = new CLIEngine({ ...require("../.eslintrc.js"), fix: true });
複製代碼
eslint
在腳本中的使用方法,更具體的能夠參考eslint文檔中Node.js API部分。api
// scripts/new.js部分
...
components.push({
label: newName,
name: newName
})
const updateConfig = function(path, components) {
writeFile(path, `module.exports = ${JSON.stringify(components)}`).then(() => {
console.log("完成components.js")
// 格式化
CLIEngine.outputFixes(cli.executeOnFiles([configPath]))
})
}
const createPackages = function(componentName) {
try {
const dir = path.resolve(__dirname, `../packages/${componentName}/`)
// 建立文件夾
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
console.log(`完成建立packages/${componentName}文件夾`)
}
// 寫入README
if (!fs.existsSync(`${dir}/README.md`)) {
writeFile(
`${dir}/README.md`,
`## ${componentName} ### 使用說明 `
).then(() => {
console.log("完成建立README")
})
}
// 寫入package.json
if (!fs.existsSync(`${dir}/package.json`)) {
writeFile(
`${dir}/package.json`,
`{ "name": "@hy/${componentName}", "version": "1.0.0", "description": "${componentName}", "main": "./dist/hy-${componentName}.umd.min.js", "keywords": [ "${componentName}", "vue" ], "author": "", "license": "ISC" } `
).then(() => {
console.log("完成建立package.json")
})
}
// 建立index.js
if (!fs.existsSync(`${dir}/index.js`)) {
writeFile(`${dir}/index.js`, `export {}`).then(() => {
console.log("完成建立index.js")
CLIEngine.outputFixes(cli.executeOnFiles([`${dir}/index.js`]))
})
}
} catch (err) {
console.error(err)
}
}
const createExample = function(componentName) {
try {
const dir = path.resolve(__dirname, `../examples/${componentName}/`)
// 建立文件夾
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
console.log(`完成建立examples/${componentName}文件夾`)
}
// 寫入index.vue
if (!fs.existsSync(`${dir}/index.vue`)) {
writeFile(
`${dir}/index.vue`,
`<template> </template> <script> import { } from '../../packages/${componentName}/index' export default { components: {} } </script> `
).then(() => {
console.log(`完成建立examples/${componentName}/index.vue文件`)
// 格式化index.vue
CLIEngine.outputFixes(cli.executeOnFiles([`${dir}/index.vue`]))
})
}
} catch (err) {
console.error(err)
}
}
...
複製代碼
// build.js
...
async function build() {
for (let i = 0, len = components.length; i < len; i++) {
const name = components[i].name
await buildService.run(
"build",
{
_: ["build", `${root}/packages/${name}/src/index.js`],
target: "lib",
name: `hy-${name}`,
dest: `${root}/packages/${name}/dist`,
// 生成格式: umd格式會同時成功demo.html commonjs,umd,umd-min
formats: "commonjs,umd-min"
// clean: false
},
["--target=all", `./packages/${name}/src/index.js`]
)
}
}
...
複製代碼
lerna
是一個多包倉庫管理的工具,能夠幫助建立、管理、發佈多包倉庫中的包。
關於lerna
我也沒有太深刻得使用,只是用到了發佈。首先在項目下執行init
初始化了項目,在每次commit
以後,能夠執行publish
。lerna
會對應代碼庫打tag,併發布到npm倉庫。併發
0.0.1爲不規範版本號,最小應該從1.0.0開始。npm publish
沒法發佈,可是lerna publish
能夠發佈。
致使結果安裝爲固定版本號,而不是以^
開頭的版本號範圍。outdate
能夠檢測到有更新,沒法經過update
升級。async
組件開發主要是在packages/<component name>/src
目錄下進行,在example/<component name>/
目錄下能夠引入該組件src
下的源文件,用一些數據來進行開發測試。組件開發和項目中的組件開發基本相同。
做爲組件庫中的組件,須要更多的考慮其通用性和易用性。不能爲了通用而加入不少的屬性,而使其失去易用性;一樣也不能爲了易用,而使其過於簡單,使用範圍過於侷限。
對於每個屬性、每一個拋出去的方法,都須要認真考慮其必要性。
惟一不一樣的地方可能須要注意的是導出的方式。
一種是直接導出組件,這種形式在使用時須要引入,而且在components
中聲明,也就是局部註冊。
另外一種是添加install
方法後導出。這種形式須要調用vue.use
方法,至關於全局註冊。