《精通react/vue组件设计》之5分钟实现一个Tag(标签)组件和Empty(空状态)组件

前言

本文是笔者写组件设计的第五篇文章,之因此会写组件设计相关的文章,是由于做为一名前端优秀的前端工程师,面对各类繁琐而重复的工做,咱们不该该循序渐进的去"辛勤劳动",而是要根据已有前端的开发经验,总结出一套本身的高效开发的方法.做为数据驱动的领导者react/vue等MVVM框架的出现,帮咱们减小了工做中大量的冗余代码, 一切皆组件的思想深得人心.因此, 为了让工程师们有更多的时间去考虑业务和产品迭代,咱们不得不掌握高质量组件设计的思路和方法.因此笔者将花时间去总结各类业务场景下的组件的设计思路和方法,并用原生框架的语法去实现各类经常使用组件的开发,但愿等让前端新手或者有必定工做经验的朋友能有所收获.javascript

今天主要带你们一块儿实现一个Tag组件和Empty(空状态)组件,在介绍组件设计以前,先给你们介绍一个免费开源的图标库icomoon,css

能够在线导入SVG格式字体,并进行编辑,而后下载来使用,在组件设计中有具体的使用介绍.

若是对于react/vue组件设计原理不熟悉的,能够参考个人以前写的组件设计系列文章:html

正文

在开始组件设计以前但愿你们对css3和js有必定的基础.咱们先看看实现后的组件效果: 前端

由图能够知道tag组件能够自定义颜色主题(color theme), 能够手动关闭标签, 空状态主要是提供用户数据展现用的, 实现起来很简单,重点在图标的使用上.

1. 组件设计思路

按照以前笔者写的组件设计原则,咱们第一步是要确认需求. 一个tag标签组件通常都会有以下需求点:vue

  • 能够改变标签颜色
  • 提供关闭标签的配置,让用户能够关闭标签
  • 关闭标签的回调,让用户能控制标签关闭后触发的动做

需求收集好以后,做为一个有追求的程序员, 会得出以下线框图:java

对于react选手来讲,若是没用typescript,建议你们都用PropTypes, 它是react内置的类型检测工具,咱们能够直接在项目中导入. vue有自带的属性检测方式,这里就不一一介绍了.

2. 基于react实现一个Tag组件

2.1. tag组件框架设计

首先咱们先根据需求将组件框架写好,这样后面写业务逻辑会更清晰:node

import React from 'react'
import classnames from 'classnames'
import styles from './index.less'

/** * 标签组件 * @param {closable} boolean 是否可关闭 * @param {onClose} func 标签关闭时的回调 * @param {color} string 标签的颜色,不设置则为默认颜色 */
export default function Tag(props) {
  let { children, closable, onClose, color } = props
  return <div className={styles.xTag} style={{ backgroundColor: color }} { children } </div>
}
复制代码

有了这个框架,咱们来一步步往里面实现内容吧. 根据需求,颜色这个属性好实现,在上述代码中已经实现了, 咱们看看closable和onClose如何实现.咱们要向关闭tag,其实是须要将这个标签隐藏,好比说使用display:none,或者从dom中移除, 笔者就参考antd的实现方式,经过display:none来实现.react

首先咱们要想在react的函数式组件操做dom, 最好的方式是使用ref, 关于ref的使用若是不熟悉的能够参考react官方文档,这里实现以下:webpack

import React from 'react'
import classnames from 'classnames'
import styles from './index.less'

/** * 标签组件 * @param {closable} boolean 是否可关闭 * @param {onClose} func 标签关闭时的回调 * @param {color} string 标签的颜色,不设置则为默认颜色 */
export default function Tag(props) {
  let { children, closable, onClose, color } = props
  let tag = React.createRef()
  let handleClose = () => {
    onClose && onClose()
    tag.current.style.display = 'none'
  }
  return <div className={classnames(styles.xTag, color ? styles.xTagHasColor : '')} style={{ backgroundColor: color }} ref={tag}> { children } { closable && <span className={styles.closeBtn} onClick={handleClose}>x</span> } </div>
}
复制代码

经过react的createRef API,咱们很方便的拿到了当前的dom对象, 在handleClose能够进行属性的分配. 组件的js代码基本实现完成了,接下来看看css:css3

.xTag {
  margin-bottom: 8px;
  margin-right: 8px;
  display: inline-block;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  padding: 0 7px;
  font-size: 12px;
  line-height: 20px;
  white-space: nowrap;
  background-color: #fafafa;
  &.xTagHasColor {
    border-color: transparent;
    color: #fff;
    .closeBtn {
      color: rgba(255, 255, 255, .6)
    }
  }
  .closeBtn {
    margin-left: 5px;
    color: rgba(0, 0, 0, 0.45);
    cursor: pointer;
  }
}
复制代码

健壮性支持:

import PropTypes from 'prop-types'
// ...
Tag.propTypes = {
  color: PropTypes.string,
  closable: PropTypes.bool,
  onClose: PropTypes.func
}
复制代码

是否是很简单? 这样一个可定制对的tag组件就完成了,关于代码中的css module和classnames的使用你们能够本身去官网学习,很是简单.

3. 基于react实现一个Empty(空状态)组件

这个组件很是好写, 目前经常使用的空状态组件通常是图片和文字组合, 图片文字均可替换,具体实现以下:

import classnames from 'classnames'
import styles from './index.less'

/** * 空状态组件 * @param {className} string 自定义类名 * @param {text} string 空状态文本 */
export default function Empty(props) {
  let { text, className } = props
  
  return <div className={classnames(styles.emptyWrap, className)}> <div className={styles.emptyInner}><span className="icon-finder"></span></div> <p>{ text ? text : '空空如也'}</p> </div>
}
复制代码

这里主要介绍icon-finder的由来.正如文章开始提到的,笔者采用icomoon做为图标库, 咱们能够在其官网上定制本身的图标,笔者大概选了40多了免费图标,项目中使用基本够用了.主要介绍一下他的具体功能:

  1. 可导入,下载,管理本身的图标库
  2. 可编辑图标,生成svg图标或者字体图标
    固然国内的iconfont也很是优秀,你们能够多尝试.

咱们将下载icomoon图标文件后,会有一个html的demo文件,里面有具体的使用方法和离线编辑功能,以下:

笔者在这里就很少作介绍了, 其次咱们也能够相似于antd同样,将icon封装成react的组件, 这样用起来也很是方便.

最后

后续笔者将会继续实现modal(模态窗), alert(警告提示), drawer(抽屉), tooltip(工具提示条), Skeleton(骨架屏), Message(全局提示), 日期/日历等组件, 来复盘笔者多年的组件化之旅. 若是想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入咱们一块儿学习讨论,共同探索前端的边界。

更多推荐

相关文章
相关标签/搜索