为何要进行组件库开发
如果你所在的公司对于页面的样式没有什么要求,那么你只要随便拿一个组件库来用就行了,比如element、iView等等,不用再重复造轮子了;
如果你目前只有个人用一个组件,或者是只对个别组件有要求,那么只要在你的工程里面开发一个.vue单文件组件就可以了;如果你的团队想要一个更加快速的开发方式,希望有一套一类应用的标准,并且对组件的样式有较高的要求,那么你就需要开发一个组件库了。
正确的学习方式
我觉得我写完这篇文章以后,大家看完可能只是能按部就班地开发一个组件库而已,而且具体的记忆和理解不是很深,所以我觉得正确的方式应该是站在巨人的肩膀上,比如去查看element组件库的源码,去了解他的文件组织方式,文档是如何管理的,主题文件是如何管理的,以及一些复杂组件是如何实现的。接下来,我们就进入正题。
步骤
我们来理一下整个步骤:
- 创建项目
- 调整项目结构
- 编写组件
- 使用vue-cli-service库模式打包编译
- 发布到npm
创建项目
# 创建目录
mkdir frog-ui
# 切换目录
cd frog-ui
# 初始化项目
vue create .
调整目录
将项目的目录调整到以下形式,该目录方式像是成了业界不成名的规定,element和iview都是以这样的方式组织的。我觉得挺好的,所以不做修改了。
其中:
|-- examples // 为原来的src目录改名而来,用于测试编写的组件
|-- packages // 用于组织我们的组件库
目录调整以后,我们需要修改相应的webpack配置,使原来的src目录指向修改后的examples目录,修改vue.config.js文件:
const path = require('path')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// 将entry指向examples
pages: {
index: {
entry: 'examples/main.js',
template: 'public/index.html',
filename: 'index.html'
}
},
// 为packages目录添加babel-loader处理
chainWebpack: config => {
config.module
.rule('js')
.include
.add(resolve('packages'))
.end()
.use('babel')
.loader('babel-loader')
.tap(options => {
return options
})
}
}
编写组件
packages目录下面的文件组织情况如下:
其中:
|-- datePicker // 新编写的组件,以datepicker为例
|-- theme-default // 主题文件
主题文件较为特殊,他作为单独的一个包进行发布引入,方便进行主题发布,后面再进行介绍。下面对datePicker进行介绍:
datePicker.vue
这是一个datePicker组件
datePicker/src/index.js
// 导入组件,组件必须声明 name
import datePicker from './src/datePicker.vue'
// 为组件提供 install 安装方法,供按需引入
datePicker.install = function (Vue) {
Vue.component(datePicker.name, datePicker)
}
// 默认导出组件
export default datePicker
批量注册组件
// 导入日期选择器组件
import datePicker from './datePicker'
// 存储组件列表
const components = [
datePicker
]
// 定义 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,
// 以下是具体的组件列表
...components
}
本地测试组件
我们的组件以及编写完成,第一步先在本地进行测试:
examples/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 导入组件库
import datePicker from './../packages/index'
import './../packages/theme-default/src/test.scss'
// 注册组件库
Vue.use(datePicker)
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
examples/views/home.vue
如何在浏览器中就可以看到我们的组件运行成功了,下一步就是要将我们的代码打包成npm库了,那么需要通过vue-cli3中vue-cli-service的库模式进行打包。
库模式打包
# package.json
"script": {
"build-lib": "vue-cli-service build --target lib --name frog-ui --dest lib packages/index.js && npm run build-theme",
}
库模式的介绍:点击这里
执行:
npm run build-lib
项目的根目录新增了lib文件夹,内容如下
其中:
- lib/frog-ui.common.js:一个给打包器用的 CommonJS 包
- lib/frog-ui.umd.js:一个直接给浏览器或 AMD loader 使用的 UMD 包
- lib/frog-ui.umd.min.js:压缩后的 UMD 构建版本
修改package.json
修改packages.json,目前我的项目的完整package.json如下:
{
"name": "frog-ui",
"version": "0.1.0",
"private": false,
"lisence": "MIT",
"main": "lib/frog-ui.umd.min.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build-lib": "vue-cli-service build --target lib --name frog-ui --dest lib packages/index.js && npm run build-theme",
"build-theme": "gulp build --gulpfile packages/theme-default/gulpfile.js && cp-cli packages/theme-default/lib lib/theme-default",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vue-router": "^3.0.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.7.0",
"@vue/cli-service": "^3.7.0",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"cp-cli": "^2.0.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^6.1.0",
"gulp-cssmin": "^0.2.0",
"gulp-sass": "^4.0.2",
"markdown-it-anchor": "^5.0.2",
"markdown-it-container": "^2.0.0",
"markdown-it-decorate": "^1.2.2",
"markdown-it-task-checkbox": "^1.0.6",
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",
"vue-markdown-loader": "^2.4.1",
"vue-template-compiler": "^2.5.21"
}
}
主要要修改的是:
{
"private": false, // 是否私有,必须指定为false才能发布到npm
"main": "lib/frog-ui.umd.min.js", // 编译后包的入口文件
}
根目录添加.npmignore文件
发布到npm下,只需要lib目录、package.json 和readme.md文件,所以需要忽略掉其他的目录
.npmignore
examples/
packages/
public/
vue.config.js
postcss.config.js
babel.config.js
*.map
发布npm
# 设置要发布的源,我发布的是通过verdaccio搭建的私库
npm config set registry http://registry.npmjs.org
# 登录
npm login
# 发布
npm publish
下图可以看到,我们的包发布成功了,关于私库的搭建可以查看我另外的文章。
总结
整个过程有一点点繁琐,但是能学到一些意外的知识,希望大家能够动手尝试。能力有限,文章中有写得不对的地方请大家见谅。如果对你有帮助的话,可以帮忙点个赞哦 ~