从零搭建Vue
组件库
一.组件库的划分
我们的划分以elementUi
为基准分为
Basic
:Button
、Icon图标
、Layout布局
、container布局容器
...Form
:Input
、Radio
、checkbox
、DatePicker
、Upload
...Data
:Table
、Tree
、Pagination
...Notice
:Alert
、Loading
、Message
...Navigation
:Tabs
、Dropdown
、NavMenu
...Others
:Popover
,Dialog
、inifiniteScroll
、Carousel
...
二.通过Vue-Cli
初始化项目
vue create m-ui
? Check the features needed for your project:
(*) Babel # babel配置
( ) TypeScript
( ) Progressive Web App (PWA) Support
( ) Router
( ) Vuex
(*) CSS Pre-processors # css预处理器
( ) Linter / Formatter
(*) Unit Testing # 单元测试
( ) E2E Testing
> Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass)
Less
Stylus
为什么选择dart-sass?
? Pick a unit testing solution:
> Mocha + Chai # ui测试需要使用karma
Jest
三.目录结构配置
│ .browserslistrc # 兼容版本
│ .gitignore
│ babel.config.js # babel的配置文件
│ package-lock.json
│ package.json
│ README.md
├─public
│ favicon.ico
│ index.html
├─src
│ │ App.vue
│ │ main.js
│ │
│ ├─packages # 需要打包的组件
│ │ button.vue
│ │ icon.vue
│ │ index.js # 所有组件的入口
│ │
│ └─styles # 公共样式
│ _var.scss
└─tests # 单元测试
└─unit
button.spec.js
四.编写插件入口
import Button from './button.vue';
import Icon from './icon.vue';
const install = (Vue) =>{ // 对外暴露install方法
Vue.component(Button.name,Button);
Vue.component(Icon.name,Icon);
}
if(typeof window.Vue !== 'undefined'){
install(Vue);
}
export default {
install
}
import mUi from './packages';
Vue.use(mUi)
我们可以通过插件的方式去引入我们的组件库
五.编写Button组件
实现功能规划
- 按钮的基本用法
- 图标按钮
- 按钮加载中状态
- 按钮组的实现
准备备用样式
$border-radius: 4px;
$primary: #409EFF;
$success: #67C23A;
$warning: #E6A23C;
$danger: #F56C6C;
$info: #909399;
$primary-hover: #66b1ff;
$success-hover: #85ce61;
$warning-hover: #ebb563;
$danger-hover: #f78989;
$info-hover: #a6a9ad;
$primary-active: #3a8ee6;
$success-active: #5daf34;
$warning-active: #cf9236;
$danger-active: #dd6161;
$info-active: #82848a;
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
(1).实现按钮的基本用法
使用type属性来定义 Button 的样式。
(2).图标按钮
带图标的按钮可增强辨识度(有文字)或节省空间(无文字)。
使用
iconfont
添加图标
创建图标组件:
(3).按钮加载中状态
要设置为 loading 状态,只要设置loading
属性为true
即可。
(4).按钮组的实现
以按钮组的方式出现,常用于多项类似操作。
六.搭建测试环境
我们需要测试ui
渲染后的结果。需要在浏览器中测试,所有需要使用Karma
Karma
配置
(1)安装karma
npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha karma-sourcemap-loader karma-spec-reporter karma-webpack mocha karma-chai
(2)配置karma文件
karma.conf.js
var webpackConfig = require('@vue/cli-service/webpack.config')
module.exports = function(config) {
config.set({
frameworks: ['mocha'],
files: ['tests/**/*.spec.js'],
preprocessors: {
'**/*.spec.js': ['webpack', 'sourcemap']
},
autoWatch: true,
webpack: webpackConfig,
reporters: ['spec'],
browsers: ['ChromeHeadless']
})
}
{
"scripts": {
"test": "karma start"
}
}
单元测试
import {
shallowMount
} from '@vue/test-utils';
import {
expect
} from 'chai'
import Button from '@/packages/button.vue'
import Icon from '@/packages/icon'
describe('button.vue', () => {
it('1.测试slot是否能正常显示', () => {
const wrapper = shallowMount(Button, {
slots: {
default: 'm-ui'
}
})
expect(wrapper.text()).to.equal('m-ui')
})
it('2.测试传入icon属性', () => {
const wrapper = shallowMount(Button, {
stubs: {
'm-icon': Icon
},
propsData: {
icon: 'edit' // 传入的是edit 测试一下 edit是否ok
}
})
expect(wrapper.find('use').attributes('href')).to.equal('#icon-edit')
})
it('3.测试传入loading,是否能,控制loading属性', () => {
const wrapper = shallowMount(Button, {
stubs: {
'm-icon': Icon
},
propsData: {
loading: true // 传入的是edit 测试一下 edit是否ok
}
})
expect(wrapper.find('use').attributes('href')).to.eq('#icon-loading');
expect(wrapper.find('button').attributes('disabled')).to.eq('disabled');
})
it('4.测试点击按钮', () => {
const wrapper = shallowMount(Button, {
stubs: ['m-icon']
})
wrapper.find('button').trigger('click')
expect(wrapper.emitted('click').length).to.eq(1);
});
// 5.测试前后图标
it('5.测试前后图标', () => {
const wrapper = shallowMount(Button, {
stubs: {
'm-icon': Icon
},
slots:{
default:'hello'
},
attachToDocument: true,
propsData: {
iconPosition: 'left',
icon: 'edit'
}
});
let ele = wrapper.vm.$el.querySelector('span');
expect(getComputedStyle(ele, null).order).to.eq('2');
wrapper.setProps({
iconPosition: 'right'
});
return wrapper.vm.$nextTick().then(() => {
expect(getComputedStyle(ele, null).order).to.eq('1');
});
});
})
七.打包组件
(1)配置打包命令
"lib": "vue-cli-service build --target lib --name m-ui ./src/packages/index.js"
(2)配置运行入口
"main": "./dist/m-ui.umd.min.js"
(3)link到全局下
npm link
八.使用VuePress
搭建文档
VuePress
基本配置:
(1).安装
npm install vuepress -D
(2).配置scripts
{
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
(3).初始化docs
增加入口页面README.MD
---
home: true
actionText: 欢迎 →
actionLink: /components/button
features:
- title: 搭建自己的组件库
details: 从0搭建自己的组件库
---
(4).配置导航
增加config.js
module.exports = {
title: 'm-ui', // 设置网站标题
description: 'ui 库', //描述
dest: './build', // 设置输出目录
port: 1234, //端口
themeConfig: { //主题配置
nav: [{
text: '主页',
link: '/'
}, // 导航条
],
// 为以下路由添加侧边栏
sidebar: {
'/components/': [{
collapsable: true,
children: [
'button'
]
}
]
}
}
}
(5).初始化配置文件 .vuepress
enhanceApp.js
-
安装包
npm install element-ui highlight.js node-sass sass-loader --save
-
link组件库
npm link m-ui
import Vue from 'vue';
import Element from 'element-ui'; // 引入elementUi
import 'element-ui/lib/theme-chalk/index.css'
import hljs from 'highlight.js'
import 'highlight.js/styles/googlecode.css' //样式文件
import mUi from 'm-ui' // 要编写对应的文档的包
import 'm-ui/dist/m-ui.css'
Vue.directive('highlight',function (el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block)=>{
hljs.highlightBlock(block)
})
})
export default ({
Vue,
options,
router,
siteData
}) => {
Vue.use(Element);
Vue.use(mUi)
}
(6).覆盖默认样式
styles/palette.styl
$codeBgColor = #fafafa // 代码背景颜色
$accentColor = #3eaf7c
$textColor = #2c3e50
$borderColor = #eaecef
$arrowBgColor = #ccc
$badgeTipColor = #42b983
$badgeWarningColor = darken(#ffe564, 35%)
$badgeErrorColor = #DA5961
.content pre{ margin: 0!important;}
.theme-default-content:not(.custom){
max-width: 1000px !important;
}
(7).创建components目录
创建demo-block
可收缩代码块
{{ controlText }}
(8).编写对应组件的md
文件
# Button组件
常用的操作按钮。
## 基础用法
基础的按钮用法。
::: slot source
:::
使用type属性来定义 Button 的样式。
::: slot highlight
```html
默认按钮
主要按钮
成功按钮
信息按钮
警告按钮
危险按钮
```
:::
九.发布到npm
配置.npmignore
配置文件
npm addUser
npm publish
十.推送到git
添加npm
图标 https://badge.fury.io/for/js
git remote add origin
git push origin master