UI组件库从1到N开发心得-组件篇

正文

距离第一篇UI组件库文章发布已通过去3个月了,在此期间利用零零散散的时间持续更新owl-ui组件库,目前owl-ui移动端组件库已经更新3大类(基础、表单、弹出层)9种组件(Button、Tabs、Input、Select、Switch、Drawer、Dialog、Picker、Toast)供使用。本篇文章主要讲述我在这3个月内开发UI组件的我的心得。若是想了解项目结构能够阅读上一篇文章,若是想了解实现原理能够阅读源码。全部链接在文章的结尾处。css

咱们从弹出层组件讲起vue

前方多图预警git

先看效果图。github



我在选择写组件的时候,首先选择作弹出层部分。为何呢?我列出如下几点。web

  1. 共性高、可复用。
  2. 兼容性高。
  3. 快速出货,提高成就感。

先说第一点:共性高、可复用api

由于本人很是笨,因此作事以前须要构思好久,这样会减小以后重复性的工做。好比在作弹出层的时候,很多人会发现以上组件的共同点。没错,他们都是显示隐藏(废话)。咱们接着往下分析,除了显示或隐藏以外,他们大部分都有遮罩层部分。还有动画效果也一致。咱们先根据这几点把功能抽象出来,如何作呢?bash

在vue和less中都有mixins方式,根据mixins咱们很方便的将组件中的共性提取出来,达到代码精简的目的。如下代码就是弹出层组件中显示隐藏功能的mixins文件。less

// src/common/mixins/visibility.js

const EVENT_TOGGLE = 'toggle'

export default {
  model: {
    prop: 'visible',
    event: EVENT_TOGGLE
  },
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    zIndex: {
      type: Number,
      default: 100
    },
    maskStyle: {
      type: Object,
      default: () => {}
    },
    containerStyle: {
      type: Object,
      default: () => {}
    }
  },
  data () {
    return {
      isVisible: false
    }
  },
  methods: {
    hide () {
      this.isVisible = false
    },
    show () {
      this.isVisible = true
    }
  },
  watch: {
    isVisible (val) {
      this.$emit('update:visible', val)
      this.$emit('callback', val)
      if (this.lockScroll) {
        document.body.style.overflow = val ? 'hidden' : ''
      }
    },
    visible: {
      handler (val) {
        this.isVisible = val
      }
    }
  },
  beforeDestroy () {
    this.lockScroll && (document.body.style.overflow = '')
  }
}
复制代码

上面主要作一件事,根据visible属性判断组件展现隐藏ide

使用方式以下:函数

// 组件文件

<script>
import visibilityMixin from 'mixins/visibility'

export default {
    mixins: [ visibilityMixin ]
}
</script>
复制代码

顺便说一下项目中运用到less的mixins运用,好比1px问题。

// src/styles/common/border.less

.min-device-pixel-ratio(@scale2, @scale3) {
  @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {
    transform: @scale2;
  }
  @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {
    transform: @scale3;
  }
}

.border-1px(@color: #DDD, @radius: 2PX, @style: solid) {
  &::before {
    content: "";
    pointer-events: none;
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    transform-origin: 0 0;
    border: 1PX @style @color;
    border-radius: @radius;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {
      width: 200%;
      height: 200%;
      border-radius: @radius * 2;
      transform: scale(.5);
    }
    @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {
      width: 300%;
      height: 300%;
      border-radius: @radius * 3;
      transform: scale(.33);
    }
  }
}

.border-top-1px(@color: #DDD, @style: solid) {
  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    border-top: 1Px @style @color;
    transform-origin: 0 0;
    .min-device-pixel-ratio(scaleY(.5), scaleY(.33));
  }
}
复制代码

该函数能够经过传参改变线的颜色和类型。

使用方式以下:

// src/styles/packages/dialog.less

@import "../common/border";

@dialog-prefix-cls: ~"@{css-prefix}dialog";

.@{dialog-prefix-cls} {
    ...
    &-btns {
        ...
        .border-top-1px(); // Here
    }
}
复制代码

合理的运用mixins可使得项目结构清晰、减小冗余代码更利于后期维护。

优化方式有不少种,每一个人有不一样的编码习惯,因人而异。可是目标都是一致的,让本身的代码变得简洁、精炼和易读。

在弹出层中将公共部分抽象封装,好比遮罩层

// src/common/components/popup-mask.vue

<template>
  <div class="popup-mask"
       :style="{ ...maskStyle, zIndex: zIndex - 1 }"
       @click.stop.prevent="handleMask"></div>
</template>

<script>
export default {
  props: {
    name: String,
    maskStyle: Object,
    zIndex: Number
  },
  methods: {
    handleMask (event) {
      this.$emit('click', event)
    }
  }
}
</script>
复制代码

第二点:兼容性高

我在工做中接触的移动端需求比较多,PC端作过一些管理后台。移动端与PC端的项目,给我最最直观的感觉是,移动端要求UI极其严格,一像素都不能差,而PC端差很少就能够了,UI设计师们也不会过多纠结PC端作出来的页面是否跟原型图彻底吻合。

在移动端,有的产品特别喜欢更改UI设计,特别是有表单部分的页面,今天产品嫌弃字体小了,明天可能以为字体又太大了;今天把输入框改为圆角,明天就喜欢直角。今天以为横向布局好,没准明天就要试试纵向布局。产品以为这么改没关系,却不知若是项目中运用了UI组件库,这么修改完后,代码冗余太多。都是为了更好的用户体验,慢慢也能理解。在那以后的几个移动端项目里,表单部分基本不会用到UI组件库。可是弹出层部分没有过多的限制,据我了解到的产品内部最统一的就是弹出层。若是有同窗想用owl-ui的弹出层部分的话,能够放心用,支持按需加载。

第三点:快速出货,提高成就感

我喜欢把长期计划拆解成多个很小的事情来作,就是制定不少小目标。比如游戏进度条同样,使其量化。之因此这么作的缘由是,我能周期性的看到个人工做成果,这样能够激励本身,提高信心。

弹出层组件中,mixins作好以后,像toast、dialog、drawer组件只剩下设计api部分而已。而picker组件是基于drawer组件来实现的内容部分而已。当picker组件实现完成,这时已经说明表单的select组件也已经完成了。提及来简单,其实作起来也不难。

最后在使用弹出层组件时,我想用api调用的方式来使用它。这里我借鉴了cube-ui的vue-create-api,可是由于部分方法不太适合我,因此我稍加改动,借鉴(抄)到本身的库中。

好比Toast组件,官网给出的使用方式以下:

const toast = this.$createToast({
    time: 1000,
    txt: 'Toast time 1s'
})
toast.show()
复制代码

我是个懒人,对我来讲使用一个消息提醒要写这么多,我就以为很烦恼,因此我在owl-ui中把vue-create-api稍加改造后,Toast使用方式以下:

this.$toast('欢迎光临')
复制代码

清爽了不少。

其余类型组件使用状况,有人喜欢整套使用,有人喜欢部分使用。而我属于后者。

结语

我写组件库的目的就两点。第一点能够帮助我从新梳理一遍vue的知识体系,了解到自身的不足,不断的克服困难,让本身成长。第二点结识更多圈内的朋友,提升见识。我会持续更新迭代owl-ui组件库,欢迎喜欢技术的朋友多提建议。最后附上吴军博士说过话,这句话让我终身受益。

什么事情从0分作到50分靠常识,从50分作到90分靠技术,从90分作到100分靠的是艺术。作到90分咱们能够经过努力能达到,至因而否能作到更好,就依人而定了。

连接

UI组件库从0到1开发心得

github

owl-ui主页

vue-create-api更改版

less版1px方案

祝工做顺利

邓文斌

2019年5月20日

相关文章
相关标签/搜索