本文是筆者寫組件設計的第五篇文章,之因此會寫組件設計相關的文章,是由於做爲一名前端優秀的前端工程師,面對各類繁瑣而重複的工做,咱們不該該循序漸進的去"辛勤勞動",而是要根據已有前端的開發經驗,總結出一套本身的高效開發的方法.做爲數據驅動的領導者react/vue等MVVM框架的出現,幫咱們減小了工做中大量的冗餘代碼, 一切皆組件的思想深得人心.因此, 爲了讓工程師們有更多的時間去考慮業務和產品迭代,咱們不得不掌握高質量組件設計的思路和方法.因此筆者將花時間去總結各類業務場景下的組件的設計思路和方法,並用原生框架的語法去實現各類經常使用組件的開發,但願等讓前端新手或者有必定工做經驗的朋友能有所收穫.javascript
今天主要帶你們一塊兒實現一個Tag組件和Empty(空狀態)組件,在介紹組件設計以前,先給你們介紹一個免費開源的圖標庫icomoon,css
能夠在線導入SVG格式字體,並進行編輯,而後下載來使用,在組件設計中有具體的使用介紹.若是對於react/vue組件設計原理不熟悉的,能夠參考個人以前寫的組件設計系列文章:html
在開始組件設計以前但願你們對css3和js有必定的基礎.咱們先看看實現後的組件效果: 前端
由圖能夠知道tag組件能夠自定義顏色主題(color theme), 能夠手動關閉標籤, 空狀態主要是提供用戶數據展現用的, 實現起來很簡單,重點在圖標的使用上.按照以前筆者寫的組件設計原則,咱們第一步是要確認需求. 一個tag標籤組件通常都會有以下需求點:vue
需求收集好以後,做爲一個有追求的程序員, 會得出以下線框圖:java
對於react選手來講,若是沒用typescript,建議你們都用PropTypes, 它是react內置的類型檢測工具,咱們能夠直接在項目中導入. vue有自帶的屬性檢測方式,這裏就不一一介紹了.首先咱們先根據需求將組件框架寫好,這樣後面寫業務邏輯會更清晰: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的使用你們能夠本身去官網學習,很是簡單.
這個組件很是好寫, 目前經常使用的空狀態組件通常是圖片和文字組合, 圖片文字均可替換,具體實現以下:
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多了免費圖標,項目中使用基本夠用了.主要介紹一下他的具體功能:
咱們將下載icomoon圖標文件後,會有一個html的demo文件,裏面有具體的使用方法和離線編輯功能,以下:
筆者在這裏就很少作介紹了, 其次咱們也能夠相似於antd同樣,將icon封裝成react的組件, 這樣用起來也很是方便.後續筆者將會繼續實現modal(模態窗), alert(警告提示), drawer(抽屜), tooltip(工具提示條), Skeleton(骨架屏), Message(全局提示), 日期/日曆等組件, 來複盤筆者多年的組件化之旅. 若是想學習更多H5遊戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們一塊兒學習討論,共同探索前端的邊界。