更新:javascript
npm install vuepress@0.14.11 -g
几天前官方发布的vuepress 1.x版本:谢谢你们支持!css
即使是一个青铜,也要用王者的心去编码!html
Github上关于Vue的UI库,大大小小不可胜数,即使是已经被推广使用的成熟库,也有不少。不少时候,咱们自研一套UI库,不是想要作得多牛逼,竞争过别人(事实咱也干不过人家,除非你不是一我的在战斗。毕竟这不只是个技术活,仍是个体力活),咱们仅仅是源自一个青铜对王者的仰望或者是为知足心里的需求。vue
这里跟你们讲一个一步一步自研UI库的故事。java
原文地址:github.com/qiud...node
项目地址:Ange UIwebpack
开发一套UI库,作成不难(这里指的是半半半成品,全品也好难。。。),作好很难。但不慌,咱有秘籍:css3
Vue.js
和CSS3
仍是有必定的技术要求。那我要多牛逼才能写好这个UI库啊?这取决于你这套UI库的实现高度。一套成熟的开源UI库通常都具有如下几个特色:git
所以,它们的目录架构也出现了主要的两种形式: github
观察社区几大UI库发现,它们都是基于webpack
搭建了本身的构建配置,包括本地开发、生产环境构建、UI库的打包等,创建一套本身的构建生态。咱们就不一样了,业余一点(实际上是善于应用开源工具),咱们的docs文档是基于vuepress的,vuepress有本身一套的构建体系,因此咱们只须要针对UI组件源码写一份打包配置就行了。
下面开始搭建打包配置(其实就是好久之前咱们作的基于webpack的构建,如今cli用得多了,配置也不会写了,码耶): 首先在根目录创建config
和build
文件夹,而后往两个目录分别新建文件,以下:
不是说只有一份打包的配置文件么?咋还多了那么多文件呢?是这样,虽然咱们是业余的,但咱也想作得专业一点对吧(有利于对配置进行扩展管理)!
咱们看 config/index.js
有什么?
webpack.lib.conf.js
中。
再看看build/webpack.base.conf.js
里面的关键配置:
entry
和
output
会被
webpack.lib.conf.js
覆写;
rules
定义一系列loader的转换规则,其中eslint的校验就是在这里定义了一个
eslint-loader
。
最后看一眼build/webpack.lib.conf.js
配置:
entry
的规则是,根据传参值(components)分别走不一样的入口文件,一种只有一个
./src/index.js
,这个是UI对外注册的入口文件(这使得咱们能够引入整个UI);另外一种是各个UI组件的注册入口文件(这使得咱们能够按需引入组件);
先给你们贴图直观感觉下源码的目录结构:
那实际打包的时候走的是哪种呢?真相是都走!在build-lib.js
中,执行了三次打包,打包输出效果以下:
前面扎好了马步,终于到修炼招式的阶段了! 咱们都知道,在应用某个插件的时候须要通过下面代码的调用:
import Ange from 'ange-ui'
Vue.use(Ange)
复制代码
好奇下Vue.use
在作什么处理呢?它其实就是注册/安装这个插件,根据use内部的定义,它经过调用install方法去注册插件,那么,Ange就必须是一个Function
(会被use当作是install
方法调用)或者是一个包含了install
方法的Object
。
道理我都懂,但是install
方法里面到底写些什么?
试想一下,咱们但愿在项目的任意位置都能引用这个插件,那咱们的每个组件是否是要在全局注册?好比经过下面这种方式全局注册组件:
Vue.component('pagination', pagination)
复制代码
没错,install
方法内部就是批量地全局注册组件。
首先咱们按照下图的方式新建目录和文件:
install
方法:
import './scss/ange.scss' // 引入组件样式表,也可让用户在使用的时候自行引入
import components from './components'
function install(Vue, opts = {}) {
Object.values(components).forEach((each) => {
Vue.component(each.name, each)
})
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
version: '1.0.0',
install,
...components
}
复制代码
核心逻辑install就是对全部的组件循环注册在全局。components目录的 index.js 则是逐个对外暴露组件对象,其次每个组件也有一个 index.js ,它的做用是为当前组件注入install方法。理所固然地,install
里面是将该组件注册在全局,因而咱们能够按需引用组件。
组件开发的通用模板
<template>
<component :is="'button'"></component>
</template>
<script>
export default {
name: 'ag-button',
props: {}
}
</script>
复制代码
component是vue的内置组件,is
参数设置成button
,代表最终渲染的html是button
标签,咱们也能够直接使用button标签,但咱们的按钮组件不必定是button,还多是a标签,为了更好的拓展,这里使用component。
声明组件参数
export default {
name: 'ag-button',
props: {
// 按钮类别
primary: Boolean,
secondary: Boolean,
dashed: Boolean,
link: Boolean,
// 按钮状态
color: {
type: String,
validator (val) {
return new Set(['success', 'warn', 'danger']).has(val)
}
},
// 按钮尺寸
size: {
type: String,
validator (val) {
return new Set(['large', 'normal', 'small']).has(val)
}
},
// 图标按钮
icon: String,
// 圆形按钮(通常结合图标按钮使用)
circle: Boolean,
// 外链按钮
external: Boolean,
// 异步按钮
loading: Boolean
}
}
复制代码
完善组件模板
<template>
<component :is="tag" class="ange-btn" :class="[ btnSize, color, { 'default': isDefault, 'primary': primary, 'secondary': secondary, 'dashed': dashed, 'link': link, 'icon': icon, 'circle': circle }]" @click="$emit('click', $event)" :disabled="loading">
<span class="ange-btn-content">
<!-- 图标按钮依赖 ag-icon 组件 -->
<ag-icon v-if="icon" :icon="icon" />
<slot /> <!-- 插槽接收按钮文本 -->
</span>
</component>
</template>
<script> export default { // ... computed: { tag () { return this.external ? 'a' : 'button' }, isDefault() { const type = [this.primary, this.secondary, this.dashed, this.link] return type.every((each) => !each) }, btnSize() { return this.size || 'normal' } } } </script>
复制代码
剩下的工做就是写好样式表了,你能够选择直接写在vue文件里面,也能够新建_scss/scss_样式表。
组件应用及效果(在线查看)
以上,便开发好一个button组件了,执行一下node build-lib.js
或者npm run build:lib
(如今package.json声明script)就能够打包这个UI框架,而后再将其发布到npm平台(若是你想...)
在线查看 Ange UI Docs 写好文档是一个库不可或缺的部分,写的过程经过实际应用各组件,还能够对其进行测试校验。前面说到,咱们的文档要基于vuepress开发,简洁的Markdown写法,非常方便。这里一篇 指南 能够很好地帮助你,它告诉了你如何搭建架构,写好配置以及部署上线,或者参考我这个 仓库 的配置。
假设docs/views/button.md
是你的button
组件的文档页面,要如何引用你的组件?
button
组件:
import '@scss/ange.scss'
import Button from '@component/button'
Vue.use(Button)
复制代码
至此,文档也就写好了!
最后的最后,按照 vuepress doc 部署到你的github仓库上就能够了!
本文经过button组件从0到1的开发,深刻浅出阐述了Vue UI框架的开发流程,你对Vue.js的理解越深,组件的功能越复杂,你就会用到更多的高级用法。经过自研UI框架,咱们也有很大的收获:
PS:CSS实际上是UI开发中占比很重的部分,你们按照本身的风格组件化开发就好。给你们推荐几个很棒的配色网站:
最后,但愿你们也能多多去尝试,这个青铜自研UI库的故事到这里就结束了。
The end.