preface

The world of Vue is already full of various UI libraries, notably ElementUI, Iview, MuseUI, etc., which are often used in our daily business development. Engineers who only use the UI library are ridiculed as API callers, a kind of contempt among engineers that will have to be returned.

Recently, I was at home, trying to feel the development process from the perspective of a mature UI library. After seeing these excellent codes, I really felt that my code smelled like shit! Without further ado, let’s start building our own UI library, starting with a look at how buttons are developed.

Use of buttons

Before we start developing buttons, let’s take a look at how they are used and what major properties or functions they have. This will be useful and significant for the rest of the API definition.

The main properties of a button are as follows:

  • Whether the rounded
  • Is there a border
  • Is it clickable (disabled)
  • color
  • The size of the
  • .

There are many more properties, but we won’t go over them here, some properties are developed, others are just copied; Let’s see how this works in real life:

< xCH-button color="primary" :disabled="true" :noBorder="true" circle size="m"> </ xCH-button >Copy the code

Directory planning before development

Clear directory planning, for the following code to bring unexpected readability. As time goes on, a project with staff changes tends to become larger and more difficult to maintain. It’s best to plan everything out in the early stages, but how many people can do that? Take a look at the directory for our button component:

Vue-cli 4.0 scaffolding is used in this project, which is roughly the same as the directory generated in previous versions. The code we wrote is basically in the SRC directory, where components is our.vue file, style is our style file, we used less in this project, which is similar to other CSS preprocessors. The more specific code logic is explained in detail below.

The definition of props

The minimum requirement for this article is that you have a basic knowledge of VUE. Before developing a component, it is best to map out its capabilities and associated properties and apis. In particular, don’t mess with the API. Any incompatible changes are a sign of immaturity and are irresponsible to the user of the component. This is why we always choose a mature and good framework, nobody wants to change incompatible code every once in a while. To get back to the topic, let’s first define the props we need:

props: {
    circle: Boolean./ / the rounded
    noBorder: Boolean./ / frame
    disabled: Boolean./ / click
    color: String./ / color
    textColor: String.// Text color
    size: {
        type: String,
        validator(value) {
            return ["l"."m"."s"."xs"].indexOf(value) ! =- 1; }}// Button size
}
Copy the code

Class: btn-circle, size: l, btn-l, class: btn-l, class: btn-l All the other properties are pretty much the same.

The computed properties of the style

Props are passed in to control whether or not a style is applied. We use vue’s object syntax

to define a calculated attribute buttonCls controls the style class section.

computed: {
    buttonCls() {
        return{[`${prefix}`] :true[`${prefix}-circle`] :!!!!!this.circle,
            [`${prefix}-no-border`] :this.noBorder === true[`${prefix}-The ${this.color}`] :!!!!!this.color,
            [`${prefix}-text-The ${this.textColor}`] :!!!!!this.textColor,
            [`${prefix}-The ${this.size}`] :!!!!!this.size }; }}Copy the code

The neat code is nice, with the variable prefix being a self-defined prefix, which is nice to distinguish between other UI libraries, ElementUI starting with el- and Iview starting with I -. Such an operation, immediately lofty up. It’s a royal button, haha.

template

The template section is relatively simple, and basically applies the props and calculation properties to the Button tag:

<template> <button type="button" :class="buttonCls" :disabled="!! this.disabled" @click="click" > <slot></slot> </button> </template>Copy the code

Main event: style

Here, the logic part is basically finished, a total of less than 50 lines of code, although el-Button is not as functional as ElementUI, but it is still a small number of everything, interested students can copy el-Button to further expand. Let’s focus on how to plan and write clean less code (this part of the code really amazes me, I have not paid much attention to CSS code before).

Before we start writing code, let’s review the key points:

  • The global styles are pulled out into separate variable files, as herevar.lessWhen writing a large project or plug-in library and facing mountains of code,People who can reuse code are happyWhat is left is to be miserable with mud people every day.
  • Each component has its own LESS file, herebutton.less
  • lessSyntax is very powerful, usually the most used is nested syntax and variable patterns, in factlessThere are a lot of powerful functions, such as functions, mixing, etc., are worth us to understand and learn

Let’s take a look at the var. Less file. There are a lot of variables in the var. Less file, such as color and padding.

@prefix: xch-;

/ / color
@primary-color : #45b984;
@blue-color : #3B91FF; //info
@green-color : #13CE66; //success
@yellow-color : #FFAE00; //warn
@red-color : #E11617; //error
@white-color : #fff;

//Dark, Gray 1-4 more
@dark-color: # 333333;
@dark1-color: # 555555;
@dark2-color: # 666666;
@dark3-color: # 777777;
@dark4-color: # 999999;

@gray-color: #c1c1c1;
@gray1-color: #d3d3d3;
@gray2-color: #eeeeee;
@gray3-color: #f3f3f3;
@gray4-color: #f5f5f5;

/ / button padding
@button-size-normal-padding: 8px 15px;
@button-size-l-padding: 10px 20px;
@button-size-m-padding: 7px 16px;
@button-size-s-padding: 5px 10px;
@button-size-xs-padding: 2px 6px;

// radius
@border-radius : 4px;

//font-size
@font-size : 14px;

// Animation
@animation-time : .3s;
@transition-time : .2s;

@box-shadow-button: 0 1px 1px 0 @gray2-color;

//disabled
@disabled-cursor: not-allowed;
@disabled-color: @dark4-color;
@disabled-border-color: @gray1-color;
@disabled-background-color: @gray4-color;
Copy the code

Button.less code, I use the method of annotation, as detailed as possible to explain the mystery

@btn-prefix: ~"@{prefix}btn"; // Define prefixes, which are common in UI component libraries

// Define a function to easily control color switching
// Darken and lighten are less ways to lighten
.btn-color(@color.@percent: 10%) {
    background-color: @color;
    border-color: darken(@color.@percent);
    color: @white-color;
    &:hover{
        border-color: lighten(@color.@percent);
        background-color: lighten(@color.@percent);
    }
    &:active {
        border-color: darken(@color.@percent);
        background-color: darken(@color.@percent); }}.@{btn-prefix} {
    border: none;
    outline: none;
    padding: @button-size-normal-padding;
    display: inline-block;
    border-radius: @border-radius;
    font-size: @font-size; .// The essence of color switching
    &.@{btn-prefix} {
        &-primary{
            .btn-color(@primary-color)}&-red {
            .btn-color(@red-color); }...&-no-border{
            box-shadow: none;
            border-color: transparent ! important;
        }
        &-circle {
            border-radius: 20px; }}// Unclickable style
    &[disabled] {
        cursor: @disabled-cursor;
        background-color: @disabled-background-color;
        border-color: @disabled-border-color;
        color: @disabled-color;
        &:hover {
            background-color: @disabled-background-color;
            border-color: @disabled-border-color;
            color: @disabled-color; }}// Control button size, actually control the padding
    &.@{btn-prefix}-l {
        padding: @button-size-l-padding;
    }
    &.@{btn-prefix}-m {
        padding: @button-size-m-padding; }... }Copy the code

Global registration and use

The last step is to register this component globally. This part of the code is in the entry file main.js, relatively simple and not too tired to describe; For those of you who are interested, consider how to define another component, button-group, to accomplish the combination of buttons.

The source code

There are also some details of the code and the specific button effects, which are not mentioned here, you can go to the source code to see more detailed code. Or directly downloaded to the local, run, run: git clone https://github.com/xch1029/vue-study.git. On the other hand, implementing some UI library-level code on your own can really improve things.