打造"皇家"按钮组件(干货满满)

前言

Vue的世界中已经充满了各类各样的UI库了,尤为出名的有ElementUI、Iview、MuseUI等,这几个也是咱们平常业务开发中常用的UI库。只使用UI库的工程师被调侃为api调用师,这算是一种工程师之间的鄙视了,这种鄙视早晚要还回去的。javascript

最近在家比较闲,尝试着以成熟UI库的视角来感觉下其的开发过程,看了这些优秀的代码,真的以为本身的代码有点屎味了!很少说了,让咱们开始打造本身的UI库吧,首先看下按钮是怎么开发出来的。css

按钮的使用

在正式开发按钮以前,咱们先看下按钮是如何使用的,以及有哪些主要属性或者功能。这对接下来的api定义是颇有用处的,意义重大。vue

按钮的主要属性有这么几点:java

  • 是否圆角
  • 是否有边框
  • 是否可点击(disabled)
  • 颜色
  • 大小
  • ...

其实还有更多的属性,这里咱们不赘述了,知道了某些属性的开发过程,其余的也只是照葫芦画瓢的;再来看下真实场景中是如何使用的:git

<xch-button color="primary" :disabled="true" :noBorder="true" circle size="m">按钮</xch-button>
复制代码

开发前的目录规划

清晰的目录规划,能为后面的代码带来意想不到的可读性。一个项目随着时间的推移,人员的变更,每每会变得愈来愈大,愈来愈难维护。能在前期就规划好一切固然是最好的,可是又有几人能作到呢。看下咱们这个按钮组件的目录:github

本项目使用的是vue-cli 4.0脚手架生成的,和之前版本生成的目录大体相同。咱们编写的代码基本都在src目录下,其中components里放的是咱们的.vue文件,style中放的是样式文件,本项目咱们采用的是less,和其余几个css预处理器都差很少。更具体的代码逻辑,在下文会依次详细解说。vue-cli

props 的定义

本文的最低要求是你已经具有了vue的基础知识。在开发一个组件以前,咱们最好的作法是规划好这个组件的能力和相关的属性以及api。特别是api,轻易不要乱改,任何不兼容的修改都是不成熟的标志,对组件的使用者来讲也是不负责任的表现,这也是为何咱们老是选择成熟优秀框架的缘由,没有人但愿隔三差五去修改不兼容的代码。回归正题,咱们首先定义下咱们须要的props:api

props: {
    circle: Boolean, // 圆角
    noBorder: Boolean, // 边框
    disabled: Boolean, // 可点击
    color: String, // 颜色
    textColor: String, // 文本颜色
    size: {
        type: String,
        validator(value) {
            return ["l", "m", "s", "xs"].indexOf(value) != -1;
        }
    } // 按钮大小
}
复制代码

先说一下思想:这些传入的props,多数是为了控制某个样式的class是否须要应用,好比,circle传入的话,就表明着应用class: btn-circlesize传入'l'的话,就表明着应用class: btn-l。其余的属性也都大体同样。框架

样式的计算属性

上文也讲了,props的传入,其实多数是为了控制某个样式是否应用。咱们使用vue的对象语法<div v-bind:class="{ active: isActive }"></div>来定义一个计算属性buttonCls控制着样式class这一块。less

computed: {
    buttonCls() {
        return {
            [`${prefix}`]: true,
            [`${prefix}-circle`]: !!this.circle,
            [`${prefix}-no-border`]: this.noBorder === true,
            [`${prefix}-${this.color}`]: !!this.color,
            [`${prefix}-text-${this.textColor}`]: !!this.textColor,
            [`${prefix}-${this.size}`]: !!this.size
        };
    }
}
复制代码

整齐划一的代码真好看,其中变量是prefix是本身定义的前缀,这样能很好的区分其余UI库,ElementUI是以el-开头,Iview是以i-开头。这么一操做,马上高大上起来了。不愧是皇家按钮, 哈哈。

template

template部分相对简单些,主要是将props和计算属性应用到button标签上:

<template>
  <button
    type="button"
    :class="buttonCls"
    :disabled="!!this.disabled"
    @click="click"
  >
    <slot></slot>
  </button>
</template>
复制代码

重头戏:样式

写到这里,逻辑部分基本写完了,一共50行不到的代码,虽然没有ElementUI的el-button的功能齐全,但也算是麻雀虽小五脏俱全吧,有兴趣的同窗能够仿照el-button进一步扩展。下面咱们重点学习下怎么规划和书写整洁的less代码(这部分代码真的惊艳到我了,我以前一直不重视css的代码)

在动手写代码以前,咱们先梳理下有哪些要点:

  • 全局的样式抽离成单独的变量文件,这里就是var.less,这个习惯必定要养成,在编写大型的项目或者插件库的时候,面对堆积成山的代码量,会复用代码的人是快乐的,剩下的就是和稀泥的人,天天痛苦不堪。
  • 每一个组件都有本身的less文件,这里是button.less
  • less语法是很强大的,平时用的最多的就是嵌套语法和变量模式,其实less还有不少的强大的功能,好比函数,混合等,都是很值得咱们去好好理解和学习的

咱们先看下var.less文件,里面咱们定义了不少变量,好比,颜色、padding等,不只是button组件会用到,之后的其余组件也会用到,先大概看下:

@prefix: xch-;

// 颜色
@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;

// 按钮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;
复制代码

button.less的代码,我使用了注释的方法,尽可能详细的解说其中的奥妙

@btn-prefix: ~"@{prefix}btn"; // 定义前缀,这是UI组件库通用的作法

// 定义一个函数,方便控制颜色的切换
// 其中的darken和lighten方法是less自带的,变浅或者变深,甚是好用
.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;
    ...
    // 颜色切换的精髓
    &.@{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;
        }
    }
    // 不可点击时的样式
    &[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;
        }
    }
    // 控制按钮大小,实际上是控制padding
    &.@{btn-prefix}-l {
        padding: @button-size-l-padding;
    }
    &.@{btn-prefix}-m {
        padding: @button-size-m-padding;
    }
    ...
}
复制代码

全局注册和使用

最后就是将本组件注册到全局,这部分代码在入口文件main.js中,比较简单就不累述了;感兴趣的同窗能够思考下怎么定义另外一个组件button-group来完成按钮的组合使用。

源码

还有些细枝末叶的代码和具体的按钮效果,这里也没有提到,能够去源码查看更多详细的代码。或者直接下载到本地,跑起来,运行下: git clone https://github.com/xch1029/vue-study.git。附上一句内心话,本身去实现一些UI库级别的代码真的能提高不少

相关文章
相关标签/搜索