前沿
目前,我们能接触到的模块化组件库真可谓是数不胜数,尤其是vue相关的那更是多如牛毛,譬如element,iview等等,虽然有很多,但是轮子虽多,合不合适自己还不好说,就像买衣服,有件衣服虽然好看,但是貌似容纳不了自身肥胖的身躯那也只能望洋兴叹。当然这时候,量身定做就显得那么重要!今天,就一起从头开始定制一套符合自身的vue组件库。
起步
首先,就已了解的组件库的写法也就那么回事,但是编写组件库的同事要写一套完善的文档也是尤为重要,经过各种方式了解到,目前我所熟知的有三种:
- storybook 相信做react开发的筒子很熟悉,但自从v3.2版本之后开始支持vue,这消息可谓是喜大普奔。
- vue-mark-down 用这个可以在markdown中演示代码案例,以及代码展示。
- docsify 这是一个快速生成doc文档的库,也是最近才了解到的。
项目初始化
开始,需要创建一个空的vue项目,在此基础上我们才能开始接下来的组件库编写!
npm i -g vue-cli // yarn add global vue-cli
vue init webpack lyui //(lyui)可以随意更换成你的名称
cd lyui
npm run dev
复制代码
不出意外,打开浏览器: http://localhost:8080,便能看到如下:
组件库结构
接下来的结构都会以一个最简单的按钮组件做讲述!所有的组件都放在src>components里面,每个组件都新建一个目录,譬如button组件,目录结构如下:
src/components/index.js
import Button from './button'
const components = {
Button
}
const install = function (Vue) {
if (install.installed) return
// components.map(component => Vue.component(component.name, component))
Object.keys(components).forEach(key => {
Vue.component(components[key].name, components[key])
})
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
const API = {
install,
...components
}
export default API
复制代码
src/components/button/index.js
import Button from './src/button.vue'
Button.install = function (Vue) {
Vue.component(Button.name, Button)
}
export default Button
复制代码
src/components/button/src/button.vue
复制代码
当然,我这里的button组件只是一个基本架构。
组件库的引用
上面写了一个按钮组件,我们当然是要把他用到我们的项目中,不知道大家是否还记得element的用法,其实我们这里的用法类似。
src/app.js
添加如下代码:
import lyui from './components/index'
Vue.use(lyui)
复制代码
现在我们的项目还没有发布到npm,就这样简单的项目内引用了,后面我们发布到npm了之后就完全可以跟element一样的使用方法了。ui库已经引用到项目中,有点迫不及待要去测试一下效果了。 src/docs/test.md
脱胎换骨
房子已经买了,总不能直接住毛坯,接下来我们就一起简单的装修一番,材料多种多样,有scss,css,postcss,看个人喜好了,这里为了方便起见,我就直接用scss了,其实更简单的是直接写在style里面,但是不推荐那样做,因为可定制性不强。 src/components/button/button.scss
.ly-button{
border:none;
padding:5px 15px;
background:#41B883;
color:#fff;
}
复制代码
src/components/index.scss
@import './button/src/button.scss'
复制代码
src/main.js
import './components/index.scss'
复制代码
上面我们简单的写了一下button的样式,并且在main.js进行引用,是不是就这样就可以了呢?答案是否定的,由于上面我们的样式是用的sass,然而我们的项目并没有任何关于sass的loader,这个简单,我们添加个sass的loader不就是了
cnpm install --save-dev sass-loader node-sass
复制代码
- 因为sass-loader依耐于node-sass,这里给个友情提示,一般情况下,我们npm又或者是yarn都不能很顺利的安装node-sass,唯一的一步到位的方式便是使用淘宝的cnpm。
npm install -g cnpm --registry=https://registry.npm.taobao.org
复制代码
安装完sass-loader、node-sass之后直接重启服务就能看到我们加的样式已经生效了!
打包发布
一个组件库写完了,最后肯定是要打包发布的,不然我们写出来就毫无意义了。新建三个配置文件: config/package.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
'lyui': './src/components/index.js'
},
output: {
path: path.resolve(__dirname, '../package'),
publicPath: '/package/',
library: 'lyui',
libraryTarget: 'umd',
umdNamedDefine: true
},
externals: {
vue: {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
}
},
resolve: {
extensions: ['.js', '.vue']
},
module: {
loaders: [{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: 'vue-style-loader!css-loader',
sass: 'vue-style-loader!css-loader!sass-loader'
},
postLoaders: {
html: 'babel-loader'
}
}
}, {
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'autoprefixer-loader'
]
}, {
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader: 'url-loader?limit=8192'
}]
},
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
}
复制代码
config/package.div.config.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./package.config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractScss = new ExtractTextPlugin('/lyui.min.css')
module.exports = merge(baseWebpackConfig, {
output: {
filename: '[name].js'
},
module: {
loaders: [{
test: /\.scss$/i,
loader: extractScss.extract(['css-loader', 'sass-loader'])
}]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"development"'
}
}),
extractScss
]
})
复制代码
config/package.prod.config.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const config = require('../config')
const baseWebpackConfig = require('./package.config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractScss = new ExtractTextPlugin('/lyui.min.css')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
output: {
filename: '[name].min.js'
},
module: {
loaders: [{
test: /\.scss$/i,
loader: extractScss.extract(['css-loader', 'sass-loader'])
}]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
//new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
uglifyOptions: {
ie8: false,
output: {
comments: false,
beautify: false,
},
mangle: {
keep_fnames: true
},
compress: {
warnings: false,
drop_console: true
}
}
}),
extractScss,
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap ?
{
safe: true,
map: {
inline: false
}
} :
{
safe: true
}
}),
new CopyWebpackPlugin([
// {output}/file.txt
{
from: `./src/components`,
to: `./components`
}
]),
]
})
复制代码
接下来需要在package.json中添加三条script
"package:dev": "webpack --config build/package.dev.config.js",
"package:prod": "webpack --config build/package.prod.config.js",
"package": "npm run package:prod && npm publish && npm run build"
复制代码
并且添加mian
"main": "package/lyui.min.js",
复制代码
最后需要在 src/components/index.js
中引用 index.scss
import './index.scss'
复制代码
npm run package \ npm run package:prod
复制代码
执行完上面的命令之后会生成package目录,里面包含打包之后的所有文件。
文档编写
上面介绍了那么多,最后写出来的东西也只有你自己看得懂,用户可是看得一脸懵逼,这时候一个好的文档就显得尤为重要,接下来开始介绍今天的主角:docsify
全局安装dosify
npm i docsify-cli -g
复制代码
初始化docsify
docsify init ./docs
复制代码
启动文档服务器
docsify serve ./docs
复制代码
启动成功之后,就可以直接打开:http://localhost:3000 接下来的很多配置的东西在这里就不累述了,docsify.js.org/,大家自行查看文档,而且配置也很简单!
结尾
虽然写了好多这种技术性文章,然而到目前为止还没有真正意义上的写一个属于自己的组件库,实在惭愧,希望大家能把这篇文章用到实处,真正意义上学有所用!