In daily business development, most of us encapsulate our own components, either business components or UI components. Of course, there are many excellent open source UI component libraries, such as Ant Design, Element UI, Material UI, etc., which can basically meet our daily development needs. However, the same world is not the same designer, and UI designers of different companies have their own different design styles. Therefore, in view of this situation, it is necessary to encapsulate and implement a SET of UI component libraries in line with their own company’s design concept.
This article gives a brief description of how to build a UI component library and documentation from scratch. The content of this article involves the process, tools and configuration of component library construction, referring to Element UI and iView.
UI component library address: zyl- UI
Document address: zyl-docs
Project structures,
Vue-cli initialization project
vue create zyl-ui
Copy the code
? Please pick a preset:
default (babel, eslint)
> Manually select features
Copy the code
Select the features you want to support
? Check the features needed for your project:
(*) Babel # Babel configuration
( ) TypeScript
( ) Progressive Web App (PWA) Support
( ) Router
( ) Vuex
(*) CSS Pre-processors # CSS preprocessor
( ) Linter / Formatter
(*) Unit Testing # Unit tests
( ) E2E Testing
Copy the code
Select the CSS preprocessor
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
> Sass/SCSS (with dart-sass) Fast, easy to install, and can be compiled into pure JavaScript code
Sass/SCSS (with node-sass)
Less
Stylus
Copy the code
Select a unit test scenario
? Pick a unit testing solution:
> Mocha + Chai # UI test using Karma
Jest
Copy the code
Directory structure and configuration
│ ├─ Public │ ├ ic.ico │ ├.html │ ├─ SRC │ ├.vue │ ├.js │ ├─ Public │ Favicon# Components for development| | button │ │ └ ─ button. Vue │ │ index, js# Entry to all components│ │ │ └ ─ styles# Public style│ _var. SCSS | icon. Js# iconfont js file| ─ tests# Unit tests| └ ─ unit | └ ─ button. The spec. Js │. Browserslistrc# Browser version compatibility Settings
│ .gitignore # ignore file
│ .babelrc Babel configuration file
│ package-lock.json
│ package.json
│ README.md
Copy the code
Component library entry
src/packages/index.js
import Button from './button/button.vue';
/ /... Other components
// Globally register components
const install = Vue= > {
Vue.component(Button.name, Button)
/ /... Other components
}
/** * It is possible for components to be introduced via script tags, such as */
if (typeofWindow.Vue ! = ='undefined') {
install(Vue) // The install method is invoked by default globally directly through script references
}
export default {
install
}
Copy the code
Using components as plug-ins:
src/main.js
import zylUI from './packages';
Vue.use(zylUI)
Copy the code
Component development
Take the Button component as an example.
Learn from Element UI to implement basic usage of buttons, buttons with ICONS, load status buttons and other functions.
API design
parameter | instructions | type | An optional value | The default value |
---|---|---|---|---|
type | type | string | primary / success / warning / danger / info | default |
icon | Icon in the name of the class | string | – | – |
loading | Loading status | boolean | – | false |
position | Icon in the location | string | left / right | left |
Global style
_var.scss
$primary: #409EFF;
$success: #67C23A;
$warning: #E6A23C;
$danger: #F56C6C;
$info: # 909399;
/ /... Other style
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
Copy the code
packages/button/button.vue
Basic structure:
Nested content in the form of slots
<template>
<button class="zyl-button" :class="btnClass" :disabled="loading" @click="$emit('click', $event)">
<! -- Short, other content -->
<span v-if="this.$slots.default">
<slot></slot>
</span>
</button>
</template>
Copy the code
Logic implementation
export default {
name: 'zyl-button'.props: {
type: {
type: String.default: ' ',
validator(type) { / / check
if(type && ! ['warning'.'primary'.'info'.'success'.'danger'].includes(type)) {
console.error('type The type is invalid! Must be: ' + ['warning'.'primary'.'info'.'success'.'danger'].join(', ') + 'One of them. ')}return true}},/ /... Other attributes
},
computed: { // Set button color according to type
btnClass() {
let classes = []
if (this.type) {
classes.push(`zyl-button-The ${this.type}`)}/ /... Other logic
return classes
}
}
}
Copy the code
The style is set
@import '@/styles/_var.scss';
// ...
.zyl-button {
border-radius: $border-radius;
border: 1px solid $border-color;
height: $height;
font-size: $font-size;
cursor: pointer;
line-height: 1;
padding: 12px 20px;
display: inline-flex;
justify-content: center;
vertical-align: middle;
user-select: none;
// ...
// Set the style of the button according to type
@each $type.$color in (primary: $primary, success: $success, info: $info, warning: $warning, danger: $danger) # {{& -$type} {
background-color: # {$color};
border-color: # {$color};
color: #fff;
fill: #fff; }}/ /... Other Style Settings
Copy the code
Thus, a simple button component is developed. To ensure that our components are healthy and stable, we also need to add unit tests.
Setting up the Test Environment
We want to test the results of the UI rendered. You need to test it in a browser, in this case using Karma.
- Install the 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
Copy the code
- Configure the Karma file
karma.conf.js
const webpackConfig = require('@vue/cli-service/webpack.config');
module.exports = function(config) {
config.set({
frameworks: ['mocha'].// Set up the test framework
files: ['tests/**/*.spec.js'].preprocessors: {
'**/*.spec.js': ['webpack'.'sourcemap']},autoWatch: true.webpack: webpackConfig,
reporters: ['spec'].browsers: ['ChromeHeadless'] // Headless browser})}Copy the code
package.json
{
"scripts": {
"test": "karma start"}}Copy the code
Writing unit tests
Using Button as an example, write unit tests.
import {shallowMount} from '@vue/test-utils'; // VUE provides a quick test method
import {expect} from 'chai';
import Button from '@/packages/button/button.vue';
// ...
describe('button.vue',()=>{
it('1. Test whether button displays slot contents properly ', () = > {// Test the current component running in the browser
const wrapper = shallowMount(Button, {
slots: {default:'zyl-ui'}}); expect(wrapper.text()).to.eq('zyl-ui');
})
/ /... Other test logic
})
Copy the code
Run the test task
npm run test
Copy the code
Component packaging
When all the component library run tests pass, our component is ready for use, and we can package the component library. Note that we can package in UMD, CommonJS or ES Module format.
- Configuring packaging Commands
package.json
{
"scripts": {
"lib": "vue-cli-service build --target lib --name zyl-ui ./src/packages/index.js"}}Copy the code
- Configure the Operation Portal
package.json
"main": "./dist/zyl-ui.umd.min.js"
Copy the code
- Link the project to the global context
Execute in the zyl-UI project root directory
npm link
Copy the code
VuePress builds documents
VuePress is a VUUe-powered static web site generator. Support the use of Vue components in Markdown for simplicity and high performance. Of course, you can also use other document generators such as Docz, Storybook, etc.
According to the official documentation to learn how to use: www.vuepress.cn/guide/getti…
Project generation and configuration
- The installation
mkdir zyl-docs && cd zyl-docs
npm init -y
npm install vuepress -D
Copy the code
- The configuration scripts
package.json
{
"docs:dev": "vuepress dev docs"."docs:build": "vuepress build docs"
}
Copy the code
- Initialize the docs
Create a docs directory under the project root
├─ Docs │ ├─ Vuepress │ components# demo
| | styles # Document presentation style
| | config.js # configuration| | enhanceApp. Js │ │ │ ├ ─ components# Documentation for all components| | button. The md │ │ │ └ ─ README. Md | │. Gitignore# ignore file
│ package-lock.json
│ package.json
│ README.md
Copy the code
docs/README.md
-- Home: true actionText: Welcome → actionLink: / Components/Button Features:- Title: Build your own component libraryBuild your own component library from 0 based on Vue2.6
Copy the code
- Configuration navigation
docs/.vuepress/config.js
module.exports = {
title: 'zyl-ui'.// Set the site title
description: 'UI Component Library'./ / description
dest: './build'.// Set the output directory
port: 1234./ / port
themeConfig: { // Theme configuration
nav: [ // The header navigation bar
{
text: 'home'.link: '/'},].// Add a sidebar for the following routes
sidebar: {
'/components/': [{title: 'Basic'.collapsable: false.children: [
'button'./ /... Other components]},// Other Settings]}}}Copy the code
-
Enhanceapp.js, an enhancement file for the client application
This file is used to add the optimized configuration shown in the component Demo
The installation
npm install element-ui highlight.js node-sass sass-loader --save Copy the code
Zyl – UI component library developed by Link
npm link zyl-ui Copy the code
.vuepress/enhanceApp.js
import Vue from 'vue'; import ElementUI from 'element-ui'; // Globally introduce element-ui import 'element-ui/lib/theme-chalk/index.css'; import hljs from 'highlight.js'; // Code highlights import 'highlight.js/styles/googlecode.css'; import zylUI from 'zyl-ui'; // To write the corresponding document package import 'zyl-ui/dist/zyl-ui.css'; // Global register directive Vue.directive('highlight'.function (el) { let blocks = el.querySelectorAll('pre code'); blocks.forEach((block) = >{ hljs.highlightBlock(block) }) }) export default ({ Vue }) => { Vue.use(ElementUI); Vue.use(zylUI) } Copy the code
The styles/palette. Styl file is used to override the default styles of vuepress, while components/ demo-blocker. Vue file is mainly a rewrite of the styles shown by the default theme demo and some definition of the display logic. The code is too long; I won’t repeat it here.
Write Markdown files for the corresponding components
For the button component example, create a button.md file under docs/ Components
# Button ButtonCommon operation buttons## Basic usageBasic button usage<demo-block>
:::slot source
<button-test1></button-test1>::: Uses the type attribute to define the style of the Button :::slot highlight (HTML)
< yl-button> default button
< yl-button type="primary"> Main button
< yl-button
< zyl - button type = "danger" > dangerous button < / zyl - button > < / div > (` ` `) : : : < / demo - block > / / slightly
Copy the code
Visit http://localhost:1234 to see the documentation. Of course, you can deploy documents to your own server, or to Github Pages, without expanding here.
Publish components to NPM
- configuration
.npmignore
file
src
public
tests
Copy the code
- release
You need to make sure these fields are in package.json before publishing.
- name
It is the name of the package published to NPM and installed. Please ensure that it is unique, you can go to the NPM first search, whether it already exists.
- version
Version number, following semantic versioning rules. Changes are made with each new release. You can use the NPM version [major.minor.patch] command to perform the update.
- main
It’s the entrance to the bag.
npm addUser If you don't have a username, register one, otherwise log in directly
npm login Log in and enter your password
npm publish # publish, execute in zyl- UI root directory
Copy the code
After a while, you can go to NPM and search for your published packages. Next you can NPM install zyl-UI to install and use your own component libraries.
conclusion
This paper mainly introduces the process of building UI component library based on Vue and building documents based on VuePress. Involves the organization of the project, component development process, unit testing, packaging, documentation, release and so on.