前⾔

Vue是⼀套⽤于构建⽤户界⾯的渐进式框架,⽬前有越来越多的开发者在学习和使⽤。⽽组件库能帮我们节省开发精⼒,⽆需所有东⻄都从头开始去做,通过⼀个个⼩组件拼接起来,就得到了我们想要的最终⻚⾯。在⽇常开发中如果没有特定的⼀些业务需求,使⽤组件库进⾏开发⽆疑是更便捷⾼效,⽽且质量也相对更⾼的⽅案。

本⽂阐述了如何基于vue⼀步步完成⼀个UI组件库的打造。

组件库官⽹

github地址

npm地址

⼀、技术栈

我们先简单了解⼀下要搭建⼀个 UI 组件库,会涉及到哪些技术栈,下⾯是我选⽤的内容:

  1. vue-cli:官⽅⽀持的 CLI 脚⼿架,提供⼀个零配置的现代构建设置;
  2. Vue: 渐进式 JavaScript 库;
  3. Jest:JavaScript 测试框架,⽤于组件库的单元测试;

⼆、组件开发

项⽬初始化

开始,需要创建⼀个空的vue项⽬,在此基础上我们才能开始接下来的组件库编写!

npm i -g vue-cli // yarn add global vue-cli
vue init webpack heaven-ui  //(heaven-ui)可以随意更换成你的名称
cd heaven-ui
npm run dev

我们安装完依赖并进⼊项⽬启动服务后vue-cli3会⾃动给我们展示⼀个默认⻚⾯,这⾥我使⽤sass,⽤于美化ui组件的样式。

⽬录结构

这是我的⽬录结构和解释

|- build/ # webpack打包配置
|- lib/ # 打包生成的文件放这里
|- src/ # 在这里写代码 |- components/ # 各个组件,每个组件是一个子目录 |- mixins/ # 复用的mixin |- utils # 工具目录 |- App.vue # 本地运行的开发预览|- index.js # 打包入口,组件的导出 |- main.js # 本地运行的运行
|- static/ # 存放一些额外的资源文件,图片之类的
|- test/ # 测试文件夹 |- specs/ # 存放所有的测试用例 |- jest.conf.js/ # jest单元测试配置
|- .npmignore
|- .gitignore
|- .babelrc
|- README.md
|- package.json

组件库结构

暴露⼀个所有组件的⼊⼝,组件详细代码只展示button部分

src/components/index.js

import Alert from './components/alert/index.js'
import Button from './components/button/index.js'
import ButtonGroup from './components/button-group/index.js'
import Checkbox from './components/checkbox/index.js'
import CheckboxGroup from './components/checkbox-group/index.js'
import DatePicker from './components/date-picker/index.js'
import Form from './components/form/index.js'
import FormItem from './components/form-item/index.js'
import Icon from './components/icon/index.js'
import Input from './components/input/index.js'
import Option from './components/option/index.js'
import Pagination from './components/pagination/index.js'
import Radio from './components/radio/index.js'
import RadioGroup from './components/radio-group/index.js'
import Rate from './components/rate/index.js'
import Select from './components/select/index.js'
import Switch from './components/switch/index.js'
import Table from './components/table/index.js'
import HTableColumn from './components/table-column/index.js'
import Tag from './components/tag/index.js'const components = [Button,ButtonGroup,Checkbox,CheckboxGroup,DatePicker,Form,FormItem,Icon,Input,Option,Pagination,Radio,RadioGroup,Rate,Select,Switch,Table,HTableColumn,Tag,]const install = function(Vue, opts = {}) {components.map(component => {Vue.component(component.name, component);})Vue.prototype.$alert = Alert;}/* 支持使用标签的方式引入 */
if (typeof window !== 'undefined' && window.Vue) {install(window.Vue);
}export default {install,Alert,Button,ButtonGroup,Checkbox,CheckboxGroup,DatePicker,Form,FormItem,Icon,Input,Option,Pagination,Radio,RadioGroup,Rate,Select,Switch,Table,HTableColumn,Tag,
}

src/components/button/index.js

import HButton from './src/button';HButton.install = function(Vue) {Vue.component(HButton.name, HButton);
};export default HButton;

组件部分⼤概是这样⼦了

打包配置

⽬录建好了,那就该填充⾎⾁了,要打包⼀个组件库项⽬,肯定是要先配置好我们的webpack,不然写了源码也没法跑起来。所以我们先定位到 build⽬录下

webpack.base.js 。存放基本的⼀些rules配置

webpack.prod.js 。整个组件库的打包配置

build/webpack.base.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')function resolve (dir) {return path.join(__dirname, '..', dir)
}module.exports = {context: path.resolve(__dirname, '../'),entry: {app: process.env.NODE_ENV === 'production' ? './src/index.js' : './src/main.js'},output: {path: config.build.assetsRoot,filename: '[name].js',publicPath: process.env.NODE_ENV === 'production'? config.build.assetsPublicPath: config.dev.assetsPublicPath},resolve: {extensions: ['.js', '.vue', '.json'],alias: {'vue$': 'vue/dist/vue.esm.js','@': resolve('src'),'untils': resolve('src/untils'),}},module: {rules: [{test: /\.vue$/,loader: 'vue-loader',options: vueLoaderConfig},{test: /\.js$/,loader: 'babel-loader',include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]},{test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('img/[name].[hash:7].[ext]')}},{test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('media/[name].[hash:7].[ext]')}},{test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('fonts/[name].[hash:7].[ext]')}},{test: /\.scss$/,loaders:['style','css','sass']}]},node: {// prevent webpack from injecting useless setImmediate polyfill because Vue// source contains it (although only uses it if it's native).setImmediate: false,// prevent webpack from injecting mocks to Node native modules// that does not make sense for the clientdgram: 'empty',fs: 'empty',net: 'empty',tls: 'empty',child_process: 'empty'}
}

build/webpack.prod.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')const env = require('../config/prod.env')const webpackConfig = merge(baseWebpackConfig, {module: {rules: utils.styleLoaders({sourceMap: config.build.productionSourceMap,extract: true,usePostCSS: true})},devtool: config.build.productionSourceMap ? config.build.devtool : false,output: {path: config.build.assetsRoot,filename: 'heaven-ui.min.js',library: 'heaven-ui',libraryTarget: 'umd'},plugins: [// http://vuejs.github.io/vue-loader/en/workflow/production.htmlnew webpack.DefinePlugin({'process.env': env}),new UglifyJsPlugin({uglifyOptions: {compress: {warnings: false}},sourceMap: config.build.productionSourceMap,parallel: true}),// extract css into its own filenew ExtractTextPlugin({filename: 'heaven-ui.min.css',}),// Compress extracted CSS. We are using this plugin so that possible// duplicated CSS from different components can be deduped.new OptimizeCSSPlugin()]
})if (config.build.productionGzip) {const CompressionWebpackPlugin = require('compression-webpack-plugin')webpackConfig.plugins.push(new CompressionWebpackPlugin({asset: '[path].gz[query]',algorithm: 'gzip',test: new RegExp('\\.(' +config.build.productionGzipExtensions.join('|') +')$'),threshold: 10240,minRatio: 0.8}))
}if (config.build.bundleAnalyzerReport) {const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPluginwebpackConfig.plugins.push(new BundleAnalyzerPlugin())
}module.exports = webpackConfig

这⾥我配置的输出⽬录为lib,打包后的结果如下图:

三、单元测试

单元测试包含以下优点:

1. 可能会测出功能的隐藏bug

2. 保证代码重构的安全性。

组件库中每⼀个组件都可能会重构或者更新迭代,如果单元测试覆盖率⾼的话,修改代码之后就越可能会发现潜在的问题。⽐如版本升级后,导致某部分功能的缺失。

组件库开发调试完成后,我们需要编写每个组件对应的单元测试,以达到100%的覆盖率为⽬标。

以button为例:

test/specs/Button.spec.js

import Vue from 'vue'
import Button from '@/components/button'describe('button.vue', () => {it('button是否存在',()=>{expect(Button).to.be.ok;})
})

四、发布NPM

发布npm之前,我们必须按照npm的发包规则来编写我们的package.json, 我们先来解决组件库打包的问题,⾸先我们需要让脚⼿架编译我们的组件代码,并输出到指定⽬录下,我们按照发包规范⼀般会输出到lib⽬录下。项⽬打包完成后,我们需要编写package⽂件的description,keywords等,具体介绍如下:

description 组件库的描述⽂本

keywords 组件库的关键词

license 许可协议

repository 组件库关联的git仓库地址

homepage 组件库展示的⾸⻚地址

main 组件库的主⼊⼝地址(在使⽤组件时引⼊的地址)

private 声明组件库的私有性,如果要发布到npm公⽹上,需删除该属性或者设置为false

publishConfig ⽤来设置npm发布的地址,这个配置作为团队内部的npm服务器来说⾮常关键,可以设置为私有的npm仓库

发布到npm的⽅法也很简单, ⾸先我们需要先注册去npm官⽹注册⼀个账号, 然后控制台登录即可,最后我们执⾏npm publish即

可.具体流程如下:

// 登录
npm login
// 发布
npm publish
// 如果发布失败提示权限问题,请执行以下命令
npm publish --access public

注意:本次publish 版本号都需要修改版本号

五、总结

我们可以⽤vue-cli 或其他⼯具另外⽣成⼀个demo项⽬,⽤这个项⽬去引⼊我们的组件库。如果你的包还没有发布出去,可以在你的

组件库项⽬⽬录下 ⽤ npm link 或者 yarn link的命令创建⼀个link

然后在你的demo⽬录下使⽤ npm link package_name 或者 yarn link package_name 这⾥的package_name就是你的组件库的

包名,然后在你的demo项⽬的⼊⼝⽂件⾥

import Vue from vue
import Heaven from 'heaven-ui'
import 'heaven-ui/dist/heaven-ui.min.css'
// 其他代码 ...Vue.use(Heaven)

这样设置好之后,我们创建的组件就可以在这个项⽬⾥使⽤了

原文链接: https://jue.leheavengame.com/article/60a89b56f631d777dcde0367

如何基于vue开发ui组件库(heaven-ui)相关推荐

  1. npm 编译打包vue_从零到一教你基于vue开发一个组件库

    前言 Vue是一套用于构建用户界面的渐进式框架,目前有越来越多的开发者在学习和使用.在笔者写完 徐小夕:如何从0到1教你搭建前端团队的组件系统​zhuanlan.zhihu.com 之后很多朋友希望了 ...

  2. cli3解决 ie11语法错误 vue_从零到一教你基于vue开发一个组件库高性能前端架构解决方案...

    Vue是一套用于构建用户界面的渐进式框架,目前有越来越多的开发者在学习和使用.虽然笔者有近2年没有从事vue的开发了,但平时一直在关注vue的更新和发展,笔者一直认为技术团队的组件化之路重点在于基础架 ...

  3. Vue 开发的组件库

    16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可. 在公司的Web前端项目开发中,多个项目采用 ...

  4. 基于Vue结合Vant组件库的仿电影APP

    Vue综合案例 Vue综合案例 一.项目概要 1.效果前瞻 2.开发流程 3.开发环境 二.初始化及必要知识点 1.初始化远程仓库 2.创建项目 3.路由规划 4.反向代理配置 5.网络请求封装 6. ...

  5. vue 字典_【开源】基于Vue的前端组件库HeyUI

    说道vue组件库,目前主流的基本就是iview和element.今天又发现一个很不错的.HeyUI. 组件也很丰富,入门比较简单. 反正开源框架我们有不嫌多,多多益善啊.感兴趣的可以看看. 关于Hey ...

  6. Vue UI组件库(Element UI库)

    1 移动端常用 UI 组件库 1. Vant Vant 4 - 轻量.可定制的移动端组件库 (vant-ui.github.io)  2. Cube UI cube-ui Document (didi ...

  7. React UI 组件库 Chakra UI - 01 v1.0介绍和快速使用

    Chakra UI Chakra UI 是简单.模块化和可访问的 UI 组件库. 本文 Chakra UI 版本:v1.6.2 基于 React 和 Emotion(CSS-IN-JS 方案库) 基于 ...

  8. UI组件库Kendo UI for Vue原生组件中文 - 按钮概述

    Kendo UI for Vue Buttons包提供了代表用户可以采取的简单操作的触发器组件. Buttons package是Kendo UI for Vue库的一部分,它为Vue生态系统提供原生 ...

  9. UI组件库Kendo UI for Vue中文入门指南(四)

    在本文中,您将通过构建一个包含 Grid.DropDownList.Window 和设计主题的小应用程序来学习如何使用Kendo UI for Vue组件. Kendo UI最新官方正式版下载 7. ...

  10. UI组件库Kendo UI for Vue中文入门指南(二)

    在本文中,您将通过构建一个包含 Grid.DropDownList.Window 和设计主题的小应用程序来学习如何使用Kendo UI for Vue组件. Kendo UI最新官方正式版下载 5. ...

最新文章

  1. 使用C++实现Socket编程传输文件
  2. 北大校长王恩哥送给毕业生的十句话
  3. 高并发大流量专题---5、CDN加速
  4. python一行输入多个值用空格隔开_2020-09-22-Python-函数嵌套、filter()函数、一行输入多个整数(空格分隔)、多维列表的输入...
  5. Intel Idea导入eclipse下的web项目并部署到tomcat
  6. northstar机器人编程_《机器人构建实战》——导读
  7. word,excel转pdf
  8. linux 驱动打印机驱动怎么安装步骤,Linux 打印机驱动安装
  9. 微型计算机经历了那几个阶段,微型计算机的发展经历了哪几个阶段,各阶段微处理器的主要特征是什么...
  10. HIS(Hospital Information System,医院信息系统)简介
  11. 好淘客饿了么返利系统-外卖返利优惠券系统-支持美团、饿了么的外卖和商超/电影票 支持多级代理返利
  12. Elephant Swap的LaaS方案优势分析,致eToken表现强势
  13. 历史上的一些重大芯片诞生回顾-推动行业发展
  14. Windows直接访问WSL2路径并直接进行读写操作,权限不足的问题
  15. 【js语法】获取星期 new Date().getDay()
  16. 2021-05-11 MongoDB面试题 MongoDB中的命名空间是什么意思
  17. DTI在早期脑发育研究中的应用
  18. 微信小程序-API的Promise化
  19. php百度大脑,百度大脑和图灵机器人制作一个简单的自动聊天机器人【PHP代码】...
  20. ios10使用 Clipboard点击无反应

热门文章

  1. android7.1刷supersu,Android怎么刷SuperSU 安卓系统刷SuperSU Pro教程
  2. 幻幕广告上线,沉浸式体验塑造大片即视感
  3. python:PTA逆转裁判
  4. 淘宝店铺运营,店铺访客增加但是浏览量减少这是为什么,应该怎样解决?
  5. 报错Replace Autoprefixer browsers option to Browserslist config.
  6. 生产计划排产软件如何解决生产难题?
  7. python 头条新闻机器人_荐GitHub:今日头条机器人
  8. 投入产出实例matlab,基于MATLAB的投入产出分析
  9. 实习僧的字体加密破解
  10. Android的权限声明