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

简介: 本文是笔者写组件设计的第五篇文章,之所以会写组件设计相关的文章,是因为作为一名前端优秀的前端工程师,面对各种繁琐而重复的工作,我们不应该按部就班的去"辛勤劳动",而是要根据已有前端的开发经验,总结出一套自己的高效开发的方法.作为数据驱动的领导者react/vue等MVVM框架的出现,帮我们减少了工作中大量的冗余代码, 一切皆组件的思想深得人心.所以, 为了让工程师们有更多的时间去考虑业务和产品迭代,我们不得不掌握高质量组件设计的思路和方法.所以笔者将花时间去总结各种业务场景下的组件的设计思路和方法,并用原生框架的语法去实现各种常用组件的开发,希望等让前端新手或者有一定工作经验的朋友能有所收获.


前言



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


今天主要带大家一起实现一个Tag组件和Empty(空状态)组件,在介绍组件设计之前,先给大家介绍一个免费开源的图标库icomoon,



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


如果对于react/vue组件设计原理不熟悉的,可以参考我的之前写的组件设计系列文章:



正文



在开始组件设计之前希望大家对css3和js有一定的基础.我们先看看实现后的组件效果:



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


1. 组件设计思路



按照之前笔者写的组件设计原则,我们第一步是要确认需求. 一个tag标签组件一般都会有如下需求点:


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


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



对于react选手来说,如果没用typescript,建议大家都用PropTypes, 它是react内置的类型检测工具,我们可以直接在项目中导入. vue有自带的属性检测方式,这里就不一一介绍了.


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



2.1. tag组件框架设计


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


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的函数式组件操作dom, 最好的方式是使用ref, 关于ref的使用如果不熟悉的可以参考react官方文档,这里实现如下:


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:

.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. 可导入,下载,管理自己的图标库



  1. 可编辑图标,生成svg图标或者字体图标


  1. 当然国内的iconfont也非常优秀,大家可以多尝试.


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



笔者在这里就不多做介绍了, 其次我们也可以类似于antd一样,将icon封装成react的组件, 这样用起来也非常方便.


目录
相关文章
|
13天前
|
JavaScript
vue 函数化组件
vue 函数化组件
|
4天前
|
JavaScript
vue组件中的插槽
本文介绍了Vue中组件的插槽使用,包括单个插槽和多个具名插槽的定义及在父组件中的使用方法,展示了如何通过插槽将父组件的内容插入到子组件的指定位置。
|
7天前
|
前端开发 JavaScript Java
SpringBoot项目部署打包好的React、Vue项目刷新报错404
本文讨论了在SpringBoot项目中部署React或Vue打包好的前端项目时,刷新页面导致404错误的问题,并提供了两种解决方案:一是在SpringBoot启动类中配置错误页面重定向到index.html,二是将前端路由改为hash模式以避免刷新问题。
45 1
|
13天前
|
存储 API
vue3中如何动态自定义创建组件并挂载
vue3中如何动态自定义创建组件并挂载
199 90
|
6天前
|
JavaScript
Vue使用element中table组件实现单选一行
如何在Vue中使用Element UI的table组件实现单选一行的功能。
23 5
Vue使用element中table组件实现单选一行
|
7天前
|
前端开发 JavaScript UED
react或者vue更改用户所属组,将页面所有数据进行替换(解决问题思路)____一个按钮使得页面所有接口重新请求
在React或Vue中,若需在更改用户所属组后更新页面所有数据但不刷新整个页面,可以通过改变路由出口的key值来实现。在用户切换组成功后,更新key值,这会触发React或Vue重新渲染路由出口下的所有组件,从而请求新的数据。这种方法避免了使用`window.location.reload()`导致的页面闪烁,提供了更流畅的用户体验。
14 1
react或者vue更改用户所属组,将页面所有数据进行替换(解决问题思路)____一个按钮使得页面所有接口重新请求
|
7天前
|
JavaScript 前端开发 应用服务中间件
本地运行打包好的React、Vue项目
本文讨论了如何本地运行打包好的React和Vue项目,并解决了使用React-Router时Tomcat部署刷新页面导致404的问题,提出了将请求转回index.html的解决方案。
11 1
本地运行打包好的React、Vue项目
|
7天前
|
前端开发
react动态生成input、select标签以及思路总结
本文介绍了在React中动态生成input和select标签的方法,包括准备数据结构、在组件挂载时动态添加状态、页面渲染以及输入处理,最后总结了实现思路。
18 1
react动态生成input、select标签以及思路总结
|
8天前
|
JavaScript
Vue2.0、Vue3.0分别使用v-model封装组件[Vue必会]
本文介绍了在Vue 2和Vue 3中如何使用`v-model`来实现组件间的双向数据绑定,包括在Vue 2中使用`value`和`input`事件,以及在Vue 3中使用`modelValue`和`update:modelValue`事件的方法。
49 22
|
3天前
|
JavaScript
vue 函数化组件
vue 函数化组件

相关实验场景

更多