UI组件库框架设计
组件库的创建步骤:搭建框架–> 编写组件 --> 测试组件 --> 发布测试 --> 文档中心 --> 组件预览 --> 持续改进
开发环境配置
项目目录
└── build/
├── webpack.base.conf.js
├── webpack.dev.conf.js
├── webpack.prod.conf.js
├── webpack.umd.conf.js
├── webpack.theme.conf.js
├── webpack.style.conf.js
└── config/
├── index.env.js
├── dev.env.js
├── pro.env.js
└── src/
├── button
| ├── index.scss
| ├── button.vue
| ├── index.js
├── index.js
// src/button/index.js
import Button from './src/button';
/* istanbul ignore next */
Button.install = function (Vue) {
Vue.component(Button.name, Button);
};
export default Button;
// src/index.js
import Button from '../src/button';
const components = [Button]
const install = function (Vue, opts = {}) { // eslint-disable-line no-unused-vars
/* istanbul ignore if */
if (install.installed) return;
components.map(component => Vue.component(component.name, component));
Vue.use(Loading.directive);
/*
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
*/
};
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
export default {
version: '1.0.0',
install,
version,
Button
};
打包配置
最后输出:
1、你可能需要提供不同模块类型的包:commonjs、umd、es模块;
2、你需要对各组件(js/css)单独打包处理,方便用户按需加载;
3、需要打包一份全部的组件js、css样式(index.css/handy.js/handy.min.js)
handy
└── es/ # es module规范的文件
├── button
| ├── index.css
| ├── index.js
└── lib/ # commonjs规范的文件
├── button
| ├── index.css
| ├── index.js
├── utils
├── index.css
├── index.js
├── handy.js
├── handy.min.js
└── types
├── index.d.ts
├── notify.d.ts
└── package.json // "typings": "types/index.d.ts", package中字段typing或types,两者是等价的
"build:umd": "cross-env NODE_ENV=production webpack --config ./build/webpack.umd.conf.js",
"build:lib": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.conf.js",
"build:theme": "cross-env NODE_ENV=production webpack --config ./build/webpack.theme.conf.js",
"build:style": "cross-env NODE_ENV=production webpack --config ./build/webpack.style.conf.js",
package.json 中,“main”: "dist/index.js"就是库使用的文件(这个文件符合 commonjs 的模块规范)
“module”: “es/index.js” 提供一个ES Module规范的使用文件,就不需要将commonjs转为ES Module
如果开发多端组件库,还要配置打包ios、android、rn
加载
- 全局加载
import handyVue from '@handyu/handy-vue';
import '@handyu/handy-vue/handy-vue.default.css'; // 引入全局样式
Vue.use(handyVue);
- 按需加载
借助ElementUI的babel-plugin-component只引入需要的组件,以达到减小项目体积的目的
或者借助ant-design的babel-plugin-import
// plugin的作用实际就是转换成require,就是
import { Button } from 'components'
// 转换成
var button = require('components/lib/button')
require('components/lib/button/style.css')
// .babelrc
{
// ...
"plugins": [["component", {
"libraryName": "@handyu/handy-vue",
"styleLibraryName": "theme"
}
]]
}
// main.js
import { Button, Alert } from '@handyu/handy-vue'
Vue.use(Button)
Vue.use(Alert)
- 也可以通过cdn引入umd模块
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/@handyu/handy-vue/handy-vue.default.css">
<script src="https://unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="https://unpkg.com/@handyu/handy-vue/handy-vue.umd.js"></script>
</head>
<body>
<div id="app">
<ha-button theme="primary">普通按钮</ha-button>
</div>
</body>
<script>
new Vue({
el: '#app'
})
</script>
</html>
组件编写
- 基础UI组件:最小化的组件,不依赖其他组件
- 复合组件:由多个组件组成,依赖现有组件
- 业务组件:带有业务功能的大量重复使用组件
业务组件,可能在组件中内置一些内容:用户名、密码的前端校验规则;对后端响应或错误规则的响应处理
对于数据的请求和处理的方式,决定它是否能成为一个业务组件
└── src/
├── button
| ├── __test__
| ├── index.spec.js
| ├── style
| ├── index.ts
| ├── index.vue
| ├── button.md
// button/src/index.vue
<template>
<div>
<button class="ha-button">{{msg}}</button>
</div>
</template>
<script>
export default {
name: "Button",
props: {
msg: String
}
}
</script>
测试环境
TDD(Test-Driven Development):测试驱动开发,注重输出结果。
BDD(Behavior Driven Development):行为驱动开发,注重测试逻辑。
使用TDD:先写测试再去开发组件(测试驱动开发)
// 安装
npm i jest @types/jest @vue/test-utils@^2.0.0-beta.2 vue-jest@^5.0.0-alpha.1 -D
// package.json
"test": "jest --config jest.config.js",
// jest.config.js
module.exports = {
clearMocks: true,
moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.(js|jsx|ts|tsx)?$': 'babel-jest'
},
testEnvironment : 'jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
transformIgnorePatterns: ['<rootDir>/node_modules/'],
testMatch: [
// '**/test/**/*.js',
'<rootDir>/src/**/**/*.spec.js',
'<rootDir>/src/**/**/*.spec.ts'
],
};
// button/__test__/index.spec.js
import {shallowMount} from '@vue/test-utils'
import Button from '../src/index.vue'
describe('Button.vue', ()=>{
it('renders props.msg when passed', ()=>{
const msg = 'new button'
const wrapper = shallowMount(Button, {
propsData: { msg }
})
expect(wrapper.findAll('.ha-button').length).toBe(1)
})
})
// 测试
npm run test
发布包
如果发布带@xxx/xxx的为范围内的包,需要注册一个npm用户帐户,且创建一个npm Org组织
// package.json
"name": "@abc/vue", // @组织名/包名
"version": "1.0.0-alpha.0", // 每一次的版本都要比上一次高
"main": "handy-vue.umd.js", // umd指定的位置
"module": "lib/handy-vue.common.js", // es module指定的位置
"style": "handy-vue.default.css", // 样式指定的位置
"typings": "types/index.d.ts", // 声明文件指定的位置
/* "files": [ // files 字段指定工程目录下面哪些文件需要发布到npm
"index.js",
"index.d.ts",
"README.md"
]*/
npm login // 输入账号名、密码、邮箱
npm publish
npm publish --access public
发布完就可以上npm查看到刚发布的包了
发布范围内的公共包(即组织包)
创建文档
图省事的,可以使用市面上的 vue-press、markdown-it、dumi、gitbook,开箱即用来一套就完事儿了
可以用webpack搭建一套可扩展的网站,网站需要展示两个模块:
- PC端展示组件API文档
- 移动端的展示组件Demo
PC端展示组件API文档:
1)可以使用vue-cli构建一个带router、store、ts的项目,把src改名为site挪回ui组件库里,其余的删掉
2)pc端共有三个部分,头部、侧边目录、内容区域(读取md文件作为内容和展示移动端预览的区域)
- 侧边栏:构建json数据结构作为目录的数据,使用v-for循环获取目录
- 内容区域:点击侧边栏目录时,跳转到对应组件内容页面,再把md文件当作组件展示出来(重点是md的loader处理,可以自己造一个)
- 移动端展示:获取点击后传过来的组件名,拼接url地址,使用iframe展示移动端页面
3)文档的响应式处理:判断是不是移动设备,如果是就跳转到移动端的页面
<script>
var CONFIG = {
pathname: '<%= htmlWebpackPlugin.options.pathname %>',
};
if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
window.location.href = CONFIG.pathname + 'demo.html';
}
</script>
移动端部分的构建和pc端的一样,只是比pc稍微简单了
其他
扩展:
- peerDependencies可以理解为同伴依赖,它表示包和包之间的宿主关系。主要用于npm插件告诉使用者, npm插件本身依赖哪些模块, 并且需要安装它。
// ant-design 这个表明使用ant-design 中的react建议大于等于16.0.0版本
"peerDependencies": {
"react": ">=16.0.0",
"react-dom": ">=16.0.0"
}
本文地址:https://blog.csdn.net/qq_14993375/article/details/108468152
推荐阅读
-
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
-
Mint UI组件库CheckList使用及踩坑总结
-
[开源] 基于Layui组件封装的后台模版,HG-Layui-UI通用后台管理框架V1.0版
-
在mpvue框架中使用Vant WeappUI组件库的注意事项【推进】
-
【分享】Vue 资源典藏(UI组件、开发框架、服务端、辅助工具、应用实例、Demo示例)
-
ASP.NET MVC+EF框架+EasyUI实现权限管理系列(2)-数据库访问层的设计Demo
-
Vue.js 的移动端组件库mint-ui实现无限滚动加载更多的方法
-
详细讲解如何创建, 发布自己的 Vue UI 组件库
-
Yii框架自定义数据库操作组件示例
-
前端笔记之Vue(四)UI组件库&Vuex&虚拟服务器初识