點贊是美德 : )html
本文主要思考的問題是如何設計組件,react 庫設計的那麼靈巧,確定不是用來作笨重的東西~前端
我將會用 截圖 + 簡述文字 + 精簡代碼
來講明react
瞭解組件設計幾個參考點:git
狀態管理
能夠分爲 有狀態組件
無狀態組件
圖解說明github
React.Component
形式建立代碼示例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/pen/pVZqjp
這個例子加入數據雙向綁定功能,這在表單操做中用的很頻繁
圖解說明
仍是用代碼說明
代碼
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/pen/GdBPZZ
經過學習本章後,你們寫具體功能代碼前,能夠先作下 UI組件架構設計
這個沒有那麼神祕,就是描述下有哪些組件、他們之間如何組裝
若是大腦中抽象的不清楚,能夠藉助原型工具設計,本身能看懂就行,不然邊寫邊設計容易亂掉
設計完成後,過幾遍沒啥問題了,再編寫具體功能