《精通react/vue組件設計》之實現一個健壯的警告提示(Alert)組件

前言

本文是筆者寫組件設計的第七篇文章, 今天帶你們實現一個自帶主題且可關閉的Alert組件, 該組件在諸如Antd或者elementUI等第三方組件庫中都會出現,主要用來提供系統的用戶反饋.javascript

之因此會寫組件設計相關的文章,是由於做爲一名前端優秀的前端工程師,面對各類繁瑣而重複的工做,咱們不該該循序漸進的去"辛勤勞動",而是要根據已有前端的開發經驗,總結出一套本身的高效開發的方法.css

前端組件通常會劃分爲以下幾種類型:html

  • 通用型組件: 好比Button, Icon等.
  • 佈局型組件: 好比Grid, Layout佈局等.
  • 導航型組件: 好比麪包屑Breadcrumb, 下拉菜單Dropdown, 菜單Menu等.
  • 數據錄入型組件: 好比form表單, Switch開關, Upload文件上傳等.
  • 數據展現型組件: 好比Avator頭像, Table表格, List列表等.
  • 反饋型組件: 好比Progress進度條, Drawer抽屜, Modal對話框等.
  • 其餘業務類型

因此咱們在設計組件系統的時候能夠參考如上分類去設計,該分類也是antd, element, zend等主流UI庫的分類方式.前端

若是對於react/vue組件設計原理不熟悉的,能夠參考個人以前寫的組件設計系列文章:vue

筆者已經將組件庫發佈到npm上了, 你們能夠經過npm安裝的方式體驗組件.java

正文

在開始組件設計以前但願你們對css3和js有必定的基礎,並瞭解基本的react/vue語法.咱們先看看實現後的組件效果:node

1. 組件設計思路

按照以前筆者總結的組件設計原則,咱們第一步是要確認需求. 一個警告提示(Alert)組件會有以下需求點:react

  • 能控制Alert組件的樣式
  • 能控制Alert組件的關閉按鈕是否顯示
  • 用戶能夠本身輸入提示內容
  • 能控制關閉按鈕的文本,或者自定義關閉按鈕
  • 支持顯示提示內容的輔助文本
  • 內置提供不一樣類型的警告提示樣式,好比成功, 錯誤, 警告等
  • 關閉提示時能提供自定義事件

需求收集好以後,做爲一個有追求的程序員, 會得出以下線框圖: webpack

對於react選手來講,若是沒用typescript,建議你們都用PropTypes, 它是react內置的類型檢測工具,咱們能夠直接在項目中導入. vue有自帶的屬性檢測方式,這裏就不一一介紹了.css3

經過以上需求分析, 咱們發現實現一個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庫截圖以下:

最後

後續筆者將會繼續實現

  • modal(模態窗),
  • badge(徽標),
  • table(表格),
  • tooltip(工具提示條),
  • Skeleton(骨架屏),
  • Message(全局提示),
  • form(form表單),
  • switch(開關),
  • 日期/日曆,
  • 二維碼識別器組件

等組件, 來複盤筆者多年的組件化之旅.

若是想獲取組件設計系列完整源碼, 或者想學習更多H5遊戲, webpacknodegulpcss3javascriptnodeJScanvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。

更多推薦

相關文章
相關標籤/搜索