前言
一直想实现一个自己的组件库,趁着前段时间抽空自己做了一个。构建之前觉得此事并不难,当真正动手去实现的时候,会出现各种问题,还好都一步步的解决了。 中文文档
技术准备:Vue2.x、VueTestUtils(测试)、Vuepress(文档) 其他准备:npm账号、阿里云服务器、域名等
构建过程
初始化
借助vue-cli初始化项目,我的选择有sass、jest(测试)等; 借助脚手架初始化的项目@vue/test-utils
会自动安装官方文档; 使用npm install -D vuepress
命令安装安装Vuepress官方文档;
在package.json
的scripts
中添加如下命令
"scripts":{"serve":"vue-cli-serviceserve",//项目运行"build":"vue-cli-servicebuild",//项目打包"test:unit":"vue-cli-servicetest:unit",//测试"docs:build":"vuepressbuilddocs",//对Vuepress的文档打包后放到服务器"docs:dev":"vuepressdevdocs",//本地运行查看Vuepress的文档"lib":"vue-cli-servicebuild--targetlibpackages/index.js"//打包用来npm发布,后面路径换成自己的路径},
目录结构
|--xixixi-ui|--.npmignore//对npm发布相关配置|--babel.config.js|--jest.config.js//测试相关配置|--README.md|--vue.config.js|--docs//Vuepress文档的内容,文件夹命名及文件位置要遵循官方配置||--README.md||--.vuepress|||--config.js|||--components//此文件夹下的vue代码可以直接在md中使用,无需再次引入||||--xxx-button.vue||||--xxx-checkbox.vue|||--public//静态资源(静态资源一定要放到此处)|||--favicon.ico|||--fonts//阿里巴巴矢量图标||--views//单个的md文件页面||--components|||--basic||||--Button.md||||--Icon.md||--guide||--install.md||--start.md|--packages//组件库的每个组件||--index.js//导出每个组件,供vue.use()||--button|||--button.vue|||--index.js|--src||--App.vue||--main.js||--views||--Home.vue|--tests//测试代码|--button.spec.js|--unit|--example.spec.js
编写组件
此处以Button代码为例展示,css省略
//button.vue<template><buttonclass="xxx-button":class="[`xxx-button--${type}`,`xxx-button--${size}`,{'is-plain':plain,'is-round':round,'is-circle':circle,'is-disabled':disabled}]":disabled="disabled"@click="handleClick"><iv-if="icon":class="icon"></i><spanv-if="$slots.default"><slot></slot></span></button></template><script>exportdefault{name:'XxxButton',props:{type:{type:String,default:'default'},plain:{type:Boolean,default:false},round:{type:Boolean,default:false},circle:{type:Boolean,default:false},icon:{type:String,default:''},disabled:{type:Boolean,default:false},size:{type:String,default:'default'},},methods:{handleClick(e){this.$emit('click',e)}}}</script>
导出对应的button
//button/index.jsimportButtonfrom'./button.vue'exportdefaultButton
把组件全局和局部暴露出去
//package/index.jsimportButtonfrom'./button'importDialogfrom'./dialog'...import'../src/assets/fonts/iconfont.css'//存储组件列表constcomponents=[Button,Dialog,//...还有多个此处略过]constinstall=function(Vue,options={}){//全局注册所有的组件components.forEach((item)=>{Vue.component(item.name,item)})}Vue.prototype.$message=Message;Vue.prototype.$notice=Notice;//判断是否是直接引入文件,如果是,就不用调用Vue.use()if(typeofwindow!=='undefined'&&window.Vue){install(window.Vue)}exportdefault{install,Button,Dialog,//...还有多个此处略过}
对组件进行单元测试。更多详细使用请参考VueTestUtils官方文档
配置jest.config.js文件
module.exports={preset:'@vue/cli-plugin-unit-jest',transform:{"^.+\\.js$":"<rootDir>/node_modules/babel-jest"},//自定义路径简称,类始于webpack中的aliasmoduleNameMapper:{"^@pack(.*)$":"<rootDir>/packages$1"},//匹配tests目录下的spec.js和test.js文件进行测试,默认值为tests/unit文件下的文件测试"testMatch":["<rootDir>/tests/**/*.spec.js","<rootDir>/tests/**/*.test.js",]}
对Button组件进行单元测试
button.spec.jsimport{mount}from'@vue/test-utils'importButtonfrom'@pack/button/button.vue'//@pack路径在jest.config.js中配置describe('button.vue',()=>{it('buttonclass',async()=>{constwrapper=mount(Button)awaitwrapper.setProps({type:'warning'})expect(wrapper.classes()).toContain('xxx-button--warning')}),it('点击button触发click事件',async()=>{constwrapper=mount(Button,{slots:{default:"按钮"}})wrapper.vm.$emit('handleClick',123)awaitwrapper.vm.$nextTick()//等待事件处理完成expect(wrapper.emitted().handleClick).toBeTruthy()})})
借助Vuepress撰写组件文档(也可选择StroyBook)此处可参考我的另一篇文档,点此访问
此处默认你已有服务器,并对nginx有一定的了解。使用npm run docs:build
命令对文档进行打包,打包后的文件会在docs/.vuepress/dist
文件夹下,把打包后的文件放到自己云服务器对应的目录下,配置对应的nginx(不同的人不同的配置,此处不再展开)。
npm发布
package.json中的'private':false
非私有,'version': '0.1.0'
保证版本不同
确保npm中没有对应命名的私包,如果已经有的话,改一下package.json中的name
运行npm run lib
命令,打包成能发布到npm的包
注册npm账号,在该项目下的cmd中键入npm login
后,输入自己的账号、密码、邮箱进行登录。(此时要保证npm的config地址必须为npm的源地址)
使用npm publish
命令发布自己的npm包,后续发布时注意修改package.json中的version
版本
总结
在从0构建整个组件的过程,一切看似很简单,但是有些东西真正去操作的时候,会出现各种各样的问题,有些东西是自己以前从未上手使用的,比如Vuepress、npm发布等,这些都或多或少的能从网上找到一些参考,但是和自己项目本身上所出现的情况又会有所不同,只要大胆的去尝试,总会解决的。 我在尝试这个组件库开发的时间段内,参考了多个组价库和文档去解决我所碰到的问题,希望看到这里的你,对你也有所帮助!