本文主要思考的問題是如何設計組件,react 庫設計的那麼靈巧,確定不是用來作笨重的東西~html
我將會用 截圖 + 簡述文字 + 精簡代碼
來講明前端
瞭解組件設計幾個參考點:react
狀態管理
能夠分爲 有狀態組件
無狀態組件
圖解說明git
React.Component
形式建立用來管理應用數據,如業務上,首頁須要數據有:github
代碼示例json
class MyComponent extends Component { constructor(props) { super(props) this.state = { 推薦分類列表:[], 推薦廣告列表:[], 推薦商品列表:[] } } render() { return <首頁>...</首頁> } }
這種組件本身不維護 狀態,數據靠屬性傳入redux
代碼示例segmentfault
function Element(props) { let val = props.val return <div>組件 - ...</div> }
職能
劃分爲 容器組件
操做組件
展現組件
圖解說明數組
這類組件自己是一個有狀態組件,像一個舞臺把你們都呈現上去, 把數據用 屬性
方式傳下去,而後子組件用 事件
方式把數據返回react-router
像上面這個商品搜索業務
代碼示例
class Container extends Component { constructor(props) { super(props) this.state = { 搜索關鍵字: '手機殼', 排序: '綜合', 商品列表: [] } } render() { return ( <div> <搜索欄 關鍵字={this.state.搜索關鍵字} onChange={...} /> <列表控制欄 排序={this.state.排序} onChange={...} /> <商品列表 商品列表={this.state.商品列表} onChange={...} /> </div> ) } }
處理交互操做,好比 搜索框、用戶註冊登陸、購物車、文章編輯、拍圖、上傳
圖解中的搜索框,接收 屬性
關鍵字
產生的新數據 事件
方式返回容器組件
代碼示例
function SearchInput(props) { let 關鍵字 = props.關鍵字 return ( <div> <input type="text" value={關鍵字} onKeyDown={props.onChange} placeholder="輸入 ...... ↩" /> </div> ) }
這種就更純粹了,只接收 屬性
數據,用來展現
圖解中的商品列表,接收 屬性
商品列表
代碼示例
function SearchInput(props) { let 商品列表 = props.商品列表 return ( <div> {商品列表.map((item, index) => ( <商品項 key={item.id} 商品信息={item} /> ))} </div> ) }
其中商品信息
組件也是一個展現組件
, 儘量的把組件拆分
其實就是在一個容器組件上,擺放了一個 控制組件
和一個 展現組件
圖解說明
咱們動手寫一下
代碼
function InputView(props) { return ( <div> <input type="text" onKeyDown={props.onChange} placeholder="輸入 ...... ↩" /> </div> ) }
處理 onKeyDown
消息,返回給父容器
代碼
function ListView(props) { return ( <ol> {props.datas && props.datas.map((item, index) => ( <li key={index.toString()}>{item}</li> ))} </ol> ) }
map
循環打印數據列表
代碼
class ContainerView extends Component { constructor(props) { super(props) this.state = {list: []} this.handleChange = this.handleChange.bind(this) } handleChange(e) { if (e.keyCode === 13) { const value = e.target.value e.target.value = '' this.setState((state, props) => { let list = state.list list.push(value) return {list} }) } } render() { return ( <div> <InputView onChange={this.handleChange} /> <ListView datas={this.state.list} /> </div> ) } }
e.keyCode === 13
表示一直監控到輸入回車,開始更新狀態
https://codepen.io/ducafecat/...
這個例子加入數據雙向綁定功能,這在表單操做中用的很頻繁
圖解說明
仍是用代碼說明
代碼
class InputView extends Component { constructor(props) { super(props) this.form = props.form // 父容器 state.form this.sync = props.sync // 父容器 sync this.handleChange = this.handleChange.bind(this) } handleChange(e) { let name = e.target.attributes.name.value let value = e.target.value this.sync({name, value}) } render() { return ( <ul> <li> <input name="input" type="text" value={this.form.input} onChange={this.handleChange} /> </li> <li> <textarea name="textarea" value={this.form.textarea} onChange={this.handleChange} /> </li> <li> <select name="select" value={this.form.select} onChange={this.handleChange} > <option value="">---</option> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </li> </ul> ) } }
props.form
是容器傳入的表單數據,結構以下{ input: '', textarea: '', select: '' }
按控件名稱 key / val
結構
props.sync
是回傳父容器的事件,相應代碼以下handleChange(e) { let name = e.target.attributes.name.value let value = e.target.value this.sync({name, value}) }
能夠發現回傳的是 {控件名, 控件值}
,這裏是簡寫(鍵、值 名相同時能夠寫一個),完整格式是
{ name: name, value: value }
代碼
function ListView(props) { let form = props.form let list = [] for (let key in form) { list.push({ key, value: form[key] }) } return ( <ul> {list && list.map((item, index) => ( <li key={index.toString()}> {item.key} - {item.value} </li> ))} </ul> ) }
這裏作展現就簡單了,接收到屬性 form
後,格式化成數組 list
,而後 map
打印
代碼
class ContainerView extends Component { constructor(props) { super(props) this.state = {form: {input: '', textarea: '', select: ''}} this.handleSync = this.handleSync.bind(this) } handleSync(item) { this.setState((prevState, props) => { let form = prevState.form form[item.name] = item.value return {form} }) } render() { return ( <div> <InputView sync={this.handleSync} form={this.state.form} /> <ListView form={this.state.form} /> </div> ) } }
handleSync
中 form[item.name] = item.value
動態更新 key / value
達到更新 state
https://codepen.io/ducafecat/...
經過學習本章後,你們寫具體功能代碼前,能夠先作下 UI組件架構設計
這個沒有那麼神祕,就是描述下有哪些組件、他們之間如何組裝
若是大腦中抽象的不清楚,能夠藉助原型工具設計,本身能看懂就行,不然邊寫邊設計容易亂掉
設計完成後,過幾遍沒啥問題了,再編寫具體功能