1 回答

TA貢獻1775條經驗 獲得超11個贊
一個網站,從功能上劃分,都能整理出一個個細小的組件,比如一個頭部,一個按鈕,一個banner,那么怎樣才能寫好一個可以在多個頁面共享數據或私有狀態的組件呢?
以一個移動端常見的header頭部為例,左邊是返回按鈕,有的還帶有文字,中間是標題文字,右邊可能有圖片或者文字。
<div>
<i>返回按鈕</i>
<span>標題</span>
<img src="" />
</div>
返回按鈕
返回文字(backText)
標題(title)
圖片或文字(icon)
返回點擊事件
圖片或文字點擊事件(handleClick)
背景樣式
文字樣式
這8個基本因素是所有頭部都共用的,有的可有,有的可無,為了保證每個網頁都能調用同一個頭部組件,又要確保文本和事件還有樣式可以自定義。將可變的因素提取出來,通過變量的方式傳入組件。
在react中,傳遞變量用this.props。
const {backText, title, icon, handleClick} = this.props
let _backText = backText || false,
_title = title || false,
_icon = icon || false
return (
<div>
<i onClick={handleClick}>{_backText}</i>
<span>{_title}</span>
<img src={_icon} />
</div>
)
在父容器里面調用header組件的用法和安卓上類似,都是通過參數初始化配置。
handleClick(){
//注意,使用context的童鞋,需要定義contextType才可以,不然會報錯
this.context.router.go(-1)
}
render() {
return (
<Header
backText="返回首頁"
title="個人中心"
icon={imgUrl}
handleClick={this.handleClick}
/>
)
}
static contextTypes = {
router: React.PropTypes.object.isRequired
};
通過簡單的配置,就能構造更多可復用的組件,組件拆的越細,復用的程度就越高,這里沒有做傳入樣式的例子,但是樣式的初始化也是類似的方法。
還有常用的組件,如彈框:
<div>
<p>標題</p>
<p>中間內容,可以是text或者帶有多個標簽樣式的text</p>
<p>
<a>左邊按鈕,通常叫做取消</a>
<a>右邊按鈕,通常叫做確認</a>
</p>
</div>
跟header組件實現一樣,首先把可變的數據部分和事件抽象出來。
標題(title)
中間內容(content)
左邊按鈕文本(leftText)
右邊按鈕文本(rightText)
左邊按鈕的點擊事件(leftClick)
右邊按鈕的點擊事件(rightClick)
render() {
const {title, content, leftText, rightText, leftClick, rightClick} = this.props
//這里再做一次判斷空數據或者為定義數據的處理,沒人能保證傳遞進來的參數一定存在或者一定不為空。
return (
<div>
<div>{title}</div>
<div>{content}</div>
<div>
<a onClick={leftClick}>{leftText}</a>
<a onClick={rightClick}>{rightText}</a>
</div>
</div>
)
}
父容器組件調用彈框組件
leftClick() {
//左邊按鈕事件
}
rightClick() {
//右邊按鈕事件
}
render() {
const content = <p><span>提示語1</span><span>提示語2</span></p>
return (
<BombBox
title="彈框標題"
content={content}
leftText="取消"
rightText="確認"
leftClick={this.leftClick}
rightClick={this.rightClick}
/>
)
}
到這里就結束了嗎?不是的,我們知道,還有一個東西叫做state,react中,控制彈框的出現和消失,通過state來控制,而我這里要講的是react和redux結合使用,發送一個dispacth action改變state的狀態,使得彈框出現和隱藏。
leftClick() {
//左邊按鈕事件,隱藏彈框,調用一個action函數,該action函數會改變reducer中state的狀態
this.props.BombAction(false)
}
rightClick() {
//右邊按鈕事件,點擊跳轉到下一個頁面的路由
this.context.router.push(`/nextRoute`)
//這里還需要做一件事,點擊確定后,首先要清除掉彈出框的true狀態,恢復成false,避免在其他頁面共用該組件的彈出框還沒點擊出發事件就已經彈出來了。這一步也可以在BombBox組件內部用componentWillUnmount()來觸發。
this.props.BombAction(false)
}
render() {
const content = <p><span>提示語1</span><span>提示語2</span></p>
//在叫做global(全局)的reducer定義1個state參數BombStatus,表示彈框的狀態,true為顯示彈框,false為隱藏彈框。默認是false
const {BombStatus} = this.props.global
return (
<div>
{
BombStatus ?
<BombBox
title="彈框標題"
content={content}
leftText="取消"
rightText="確認"
leftClick={this.leftClick}
rightClick={this.rightClick}
/> : false
}
</div>
)
}
static contextTypes = {
router: React.PropTypes.object.isRequired
};
到這里,一個基本的可復用彈框組件就完成了,在任意一個頁面,調用該組件的方法都是一樣的,即發送一個action去改變state的狀態,然后讓彈框組件加載進來。隱藏也是改變state的狀態。
還有很多的例子,比如表格,li列表(常見在分頁組件上)等等。。。。
無論是一個簡單的組件,還是一個復雜的組件,都要記住一點,先抽象出來可變的內容和事件,然后通過action去控制組件的state狀態,不要在組件內部去用setState和getState,前提是你也是用redux來管理state。
組件是個view,要保證組件的純凈,這樣服用的程度就會更高。
- 1 回答
- 0 關注
- 670 瀏覽
添加回答
舉報