《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

徐小夕 等级 584 0 0

《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

前言

本文是笔者写组件设计的第七篇文章, 今天带大家实现一个自带主题且可关闭的Alert组件, 该组件在诸如Antd或者elementUI等第三方组件库中都会出现,主要用来提供系统的用户反馈.

之所以会写组件设计相关的文章,是因为作为一名前端优秀的前端工程师,面对各种繁琐而重复的工作,我们不应该按部就班的去"辛勤劳动",而是要根据已有前端的开发经验,总结出一套自己的高效开发的方法.

前端组件一般会划分为如下几种类型:

  • 通用型组件: 比如Button, Icon等.
  • 布局型组件: 比如Grid, Layout布局等.
  • 导航型组件: 比如面包屑Breadcrumb, 下拉菜单Dropdown, 菜单Menu等.
  • 数据录入型组件: 比如form表单, Switch开关, Upload文件上传等.
  • 数据展示型组件: 比如Avator头像, Table表格, List列表等.
  • 反馈型组件: 比如Progress进度条, Drawer抽屉, Modal对话框等.
  • 其他业务类型

所以我们在设计组件系统的时候可以参考如上分类去设计,该分类也是antd, element, zend等主流UI库的分类方式.

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

笔者已经将组件库发布到npm上了, 大家可以通过npm安装的方式体验组件.

正文

在开始组件设计之前希望大家对css3和js有一定的基础,并了解基本的react/vue语法.我们先看看实现后的组件效果:

《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

1. 组件设计思路

按照之前笔者总结的组件设计原则,我们第一步是要确认需求. 一个警告提示(Alert)组件会有如下需求点:

  • 能控制Alert组件的样式
  • 能控制Alert组件的关闭按钮是否显示
  • 用户可以自己输入提示内容
  • 能控制关闭按钮的文本,或者自定义关闭按钮
  • 支持显示提示内容的辅助文本
  • 内置提供不同类型的警告提示样式,比如成功, 错误, 警告等
  • 关闭提示时能提供自定义事件

需求收集好之后,作为一个有追求的程序员, 会得出如下线框图: 《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

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

通过以上需求分析, 我们发现实现一个Alert非常简单, 它属于反馈型组件,所以不会涉及到太多功能.接下来我们就来看看具体实现.

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

2.1. Alert组件框架设计

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

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

/**
 * 警告提示组件
 * @param {style} object 更改Alert样式
 * @param {closable} bool 是否显示关闭按钮, 默认不显示
 * @param {closeText} string|reactNode 自定义关闭按钮
 * @param {message} string 警告提示内容
 * @param {description} string 警告提示的辅助性文字
 * @param {type} string 警告的类型
 * @param {onClose} func 关闭时触发的事件
 */
function Alert(props) {
  const {
    style,
    closable,
    closeText,
    message,
    description,
    type,
    onClose
  } = props

  return <div className={styles.xAlertWrap}>
          <div className={styles.alertMes}>{ message }</div>
          <div className={styles.alertDesc}>{ description }</div>
          <span className={styles.closeBtn}>{ closeText ? closeText : 'x' }</span>
         </div>
}

export default Alert

有了这个框架,我们来一步步往里面实现内容吧.

2.2 实现style, closeText,message, description, type

这几个功能在框架搭建好之后已经部分实现了,是因为他们都比较简单,不会牵扯到其他复杂逻辑.只需要对外暴露属性并使用属性即可. 具体实现如下:

function Alert(props) {
  const {
    style,
    closable,
    closeText,
    message,
    description,
    type,
    onClose
  } = props

  return <div 
      className={classnames(styles.xAlertWrap, styles[type] || styles.warning)}
      style={{
        ...style
      }}
    >
      <div className={styles.alertMes}>{ message }</div>
      <div className={styles.alertDesc}>{ description }</div>
      <span className={styles.closeBtn}>{ closeText ? closeText : 'x' }</span>
    </div>
}

以上代码可以发现笔者采用了classnames这个第三方工具, 他可以组合我们的class以实现更灵活的配置. 对于type的实现,我的思路是提前预制好几种类型样式, 通过用户手动配置来匹配到对应的样式:

.xAlertWrap {
  box-sizing: border-box;
  position: relative;
  padding: 5px 12px;
  margin-bottom: 16px;
  border-radius: 3px;
  &.success {
    background-color: #f6ffed;
    border: 1px solid #b7eb8f;
  }
  &.info {
    background-color: #e6f7ff;
    border: 1px solid #91d5ff;
  }
  &.error {
    background-color: #fffbe6;
    border: 1px solid #ffe58f;
  }
  &.warning {
    background-color: #fff1f0;
    border: 1px solid #ffa39e;
  }
}

2.3 实现closable和onClose

closable主要是用来让用户能手动关闭Alert,onClose是对外暴露的关闭时的方法, 因为没必要也不需要向外暴露属性来让Alert关闭, 所以最好的方式是在组件内部实现, 我们会通过useState这个钩子来处理,代码如下:

function Alert(props) {
  const {
    style,
    closable,
    closeText,
    message,
    description,
    type,
    onClose
  } = props
  let [visible, setVisible] = useState(true)

  const handleColse = () => {
    setVisible(false)
    onClose && onClose()
  }
  return visible ? 
    <div 
      className={classnames(styles.xAlertWrap, styles[type] || styles.warning)}
      style={{
        opacity: visible ? '1' : '0',
        ...style
      }}
    >
      <div className={styles.alertMes}>{ message }</div>
      <div className={styles.alertDesc}>{ description }</div>
      {
        !!closable && <span className={styles.closeBtn} onClick={handleColse}>{ closeText ? closeText : 'x' }</span>
      }
    </div> : null
}

通过控制visible来控制Alert的出现和消失, 并且当点击关闭按钮时能调用外部暴露的onClose方法.

2.4 健壮性支持, 我们采用react提供的propTypes工具:

import PropTypes from 'prop-types'
// ...
Alert.propTypes = {
  style: PropTypes.object,
  closable: PropTypes.bool,
  closeText: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.element
  ]),
  message: PropTypes.string,
  description: PropTypes.string,
  type: PropTypes.string,
  onClose: PropTypes.func
}

关于prop-types的使用官网上有很详细的案例,这里说一点就是oneOfType的用法, 它用来支持一个组件可能是多种类型中的一个. 组件完整css代码如下:

.xAlertWrap {
  box-sizing: border-box;
  position: relative;
  padding: 5px 12px;
  margin-bottom: 16px;
  border-radius: 3px;
  &.success {
    background-color: #f6ffed;
    border: 1px solid #b7eb8f;
  }
  &.info {
    background-color: #e6f7ff;
    border: 1px solid #91d5ff;
  }
  &.error {
    background-color: #fffbe6;
    border: 1px solid #ffe58f;
  }
  &.warning {
    background-color: #fff1f0;
    border: 1px solid #ffa39e;
  }

  .alertMes {
    margin-bottom:5px;
    color: rgba(0, 0, 0, 0.85);
    font-size: 14px;
    line-height: 1.5em;
  }
  .alertDesc {
    color: rgba(0, 0, 0, 0.65);
    font-size: 14px;
    line-height: 1.5em;
    word-break: break-all;
  }
  .closeBtn {
    position: absolute;
    right: 8px;
    top: 5px;
    color: rgba(0, 0, 0, 0.4);
    cursor: pointer;
  }
}

通过以上步骤, 一个健壮的的Alert组件就完成了,关于代码中的css module和classnames的使用大家可以自己去官网学习,非常简单.如果不懂的可以在评论区提问,笔者看到后会第一时间解答.

2.5 使用Alert组件

我们可以通过如下方式使用它:

<Alert message="温馨提示,你忘带口罩了" />
<Alert message="温馨提示,你注册成功" type="success" />
<Alert message="错误提示,你没洗手了" type="error" />
<Alert message="提示: 我们开始吧" type="info" />
<Alert message="提示: 我可以关闭了" type="info" closable onClose={() => { alert(111) }} />
<Alert message="注册成功" description="你在本网站已经注册成功,谢谢您的支持和反馈,多交流真正的技术吧" closable type="success" />

笔者已经将实现过的组件发布到npm上了,大家如果感兴趣可以直接用npm安装后使用,方式如下:

npm i @alex_xu/xui

// 导入xui
import { 
  Button,
  Skeleton,
  Empty,
  Progress,
  Tag,
  Switch,
  Drawer,
  Badge,
  Alert
} from '@alex_xu/xui'

该组件库支持按需导入,我们只需要在项目里配置babel-plugin-import即可,具体配置如下:

// .babelrc
"plugins": [
  ["import", { "libraryName": "@alex_xu/xui", "style": true }]
]

npm库截图如下:

《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

最后

后续笔者将会继续实现

  • modal(模态窗),
  • badge(徽标),
  • table(表格),
  • tooltip(工具提示条),
  • Skeleton(骨架屏),
  • Message(全局提示),
  • form(form表单),
  • switch(开关),
  • 日期/日历,
  • 二维码识别器组件

等组件, 来复盘笔者多年的组件化之旅.

如果想获取组件设计系列完整源码, 或者想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件

更多推荐

收藏
评论区

相关推荐

基于jsoneditor二次封装一个可实时预览的json编辑器组件(react版)
前言 做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,vue或react等MVVM框架提倡组件化开发,这样一方面可以提高组件复用性和可扩展性,另一方面也带来了项目开发的灵活性和可维护,方便多人开发协作.接下来文章将介绍如何使用react,开发一个自定义json编辑器组件.我们这里使用了jsoneditor
《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件
前言 作为一个前端框架的重度使用者,在技术选型上也会非常注意其生态和完整性.笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, antdesignvue, iView等成熟的UI框架, react生态的antdesign, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和
《精通react/vue组件设计》之实现一个健壮的警告提示(Alert)组件
前言 本文是笔者写组件设计的第七篇文章, 今天带大家实现一个自带主题且可关闭的Alert组件, 该组件在诸如Antd或者elementUI等第三方组件库中都会出现,主要用
Taro 入门教程
简介 Taro 是一个遵循 React 语法规范的开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/
【Flutter实战】状态管理
3.2 状态管理响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在React/Vue(两者都是支持响应式编程的Web开发框架)还是Flutter中,他们讨论的问题和解决的思想都是一致的。所以,如果你对React/Vue的状态管理有了解,可以跳过本节。言归正传,我们想一个问题,StatefulWidget的状态应该被谁管理?
项目中的富文本编辑器该如何选择?
项目中经常需要用到富文本编辑器的时候,而常见的富文本编辑器都有哪些?该如何选择?先看看市面上都有哪些可用的富文本编辑器: (插件式的,支持 Vue,React,Angular 框架) (Typescript 开发的 Web 富文本编辑器, 轻量、简洁、易用、开源免费,支持 JS 直接引入使用,或者 Vue2/3,React) (开源,插件多,功能齐全,支持
219. 单页应用 会话管理(session、cookie、jwt)
> 原文链接:[https://github.com/ly525/blog/issues/219](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fly525%2Fblog%2Fissues%2F219) 关键字:`http-only`, `cookie`,`se
219. 单页应用 会话管理(session、cookie、jwt)
> 原文链接:[https://github.com/ly525/blog/issues/219](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fly525%2Fblog%2Fissues%2F219) 关键字:`http-only`, `cookie`,`se
Angular React Vue我应该选择什么?
2017 年比较 Angular、React、Vue 三剑客 ============================== 为 web 应用选择 JavaScript 开发框架是一件很费脑筋的事。现如今 [Angular](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Flink.juej
JFinal使用笔记5
1、前台代码 $.ajax({ type : "POST", url : "/activity", dataType : "json", success : function(data) { alert("success"); conso
React与Vue的相同与不同点
我们知道JavaScript是世界上最流行的语言之一,React和Vue是JS最流行的两个框架。所以要想前端的开发那么必须掌握好这两个框架。 那么这两个框架有什么不同呢? **React 和 Vue 相同之处,它们都有:** * 使用 Virtual DOM * 提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件
React实战之React+Redux实现一个天气预报小项目
![](https://oscimg.oschina.net/oscnet/355a9b3e0af9e3410d9cf918fdfe69b2379.jpg)**引言** ------------------------------------------------------------------------------------ 经过一段时间的Re
React的Sass配置
React提供的脚手架[creact-react-app](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Ffacebook.github.io%2Fcreate-react-app%2Fdocs%2Fadding-a-sass-stylesheet)创建的工程文件不像vue那种暴露出web
React面试必问Fiber和Hooks,一次搞定
国内的前端领域,Vue 和 React 是最火的两个框架,要说岗位数量,Vue可能会更多一点。 但如果把公司范围缩小到大厂,或者把范围扩展到全球,那React无疑独占鳌头。 ![](https://oscimg.oschina.net/oscnet/ba57134c-6a7d-47d8-a317-7ad3976a1a77.jpg "2019年
Storybook for vue
一、简介 ====   Storybook是一款开源的组件开发工具,它可以运行在主程序之外,因此开发者可以用它来独立开发UI组件,或者用它来快速构建ui组件文档。   目前Storybook支持的框架有: * React * React Native  * Vue * Angular * Marionette.js * Mith