props和state都用于描述組件特性,但是,兩者有本質區(qū)別。前者是由父組件定義的屬性變量,后者是組件本身持有的變量。并且,props一旦被定義,就不會再更改;但是,state會隨著交互變化而變化。
下面,逐一分析。
1. props
props是properties的縮寫,顧名思義,就是屬性變量。props用于在父子組件之間傳遞信息,這種傳遞是單向的,從父組件到子組件。props一旦被定義,就不可以再修改。
2.state
state是組件維護自身狀態(tài)的變量,當state更改時,組件會嘗試重新渲染。這也充分說明了React數(shù)據(jù)和模板是單向綁定,數(shù)據(jù)變化驅動模板更新。
更新state值需要調用組件接口setState
。
3. 實例
與交互無關的數(shù)據(jù)一般都定義在props中并渲染出來,對于用戶輸入,服務器請求或者其他交互變化的響應,需要用state來維護。
下面是一個簡單的例子(在Input里面輸入任意字符,點擊button,會將輸入的文字顯示在Input框下部,用<li>
標簽顯示)。
react demo 1.png
class Dashboard extends React.Component {
constructor(props) {
super(props);
// 初始化state值
this.state = {data: [], newItem: ""};
// 事件函數(shù)需要指定調用對象
this.updateNewItem = this.updateNewItem.bind(this);
this.addItem = this.addItem.bind(this);
}
// 更新state.newItem的值
updateNewItem(event) {
this.setState({newItem: event.target.value});
}
// 更新state.newItem和state.data的值
addItem(event) {
this.state.data.push(this.state.newItem);
this.setState({newItem: ""});
}
render() {
return (<div className="dashboard">
<input type="text" value={this.state.newItem} onChange={this.updateNewItem}/>
<button onClick={this.addItem}>{this.props.text}</button>
<ItemList data={this.state.data}/>
</div>);
}
}
class ItemList extends React.Component {
render() {
var listData = this.props.data.map((item, index) => {
return (<Item text={item} name="item" color="blue" key={index}/>);
});
return (<ul>{listData}</ul>);
}
}
class Item extends React.Component {
// 根據(jù)父組件傳遞的屬性值props渲染子組件
render(){
return (<li name={this.props.name} className={this.props.color}>{this.props.text}</li>);
}
}
ReactDOM.render(
<Dashboard text="Add!"/>,
document.getElementById('container')
);
4. props.children
props.children可以訪問到組件的子組件集合。如果只有一個子組件,那么返回該子組件對象;如果有多個子組件,則返回包含所有子組件的集合對象。
React提供了幫助函數(shù)React.Children.XXX來操作props.children
集合對象,幫助函數(shù)有:map
,forEach
,count
等。
下面是一個創(chuàng)建按鈕組件的例子,利用React.Children.map遍歷子組件并給子組件添加統(tǒng)一的屬性值。
react demo 2.png
<style>
.blue { color: blue; }
</style>
class ButtonGroup extends React.Component {
constructor(props) {
super(props);
}
renderChildren() {
// 利用React.Children.map遍歷所有子組件<ButtonOption>對象
return React.Children.map(this.props.children, (child) => {
// 復制子組件,并且給全部子組件添加新屬性{color: "blue"}
return React.cloneElement(child, {
color: "blue"
})
});
}
render() {
return (<div>{this.renderChildren()}</div>);
}
}
class ButtonOption extends React.Component {
render() {
return (<button className={this.props.color} value={this.props.value}>{this.props.text}</button>);
}
}
ReactDOM.render(
<ButtonGroup>
<ButtonOption text="left" value="0"></ButtonOption>
<ButtonOption text="center" value="1"></ButtonOption>
<ButtonOption text="right" value="2"></ButtonOption>
</ButtonGroup>,
document.getElementById('container')
);
下一節(jié):React入門系列(六)組件間通信