setSate
咱們先看幾個關於setState的demo,用於黑箱推測原理:函數
1) "打印0"——說明setState至關於發佈訂閱中的發佈,只是把多個狀態變動需求統一放入隊列updateQueue;this
"打印2"——說明存在一個專門用於開啓/關閉**批量**更新模式的控制器batchUpdate。 基本流程:開啓控制器 —— 入隊列(updateQueue和callbackQueue) —— 合併updateQueue中state的變化 —— 根據變化來更改state —— 執行callbackQueue —— 關閉控制器; 整個流程是同步的。
class Mine extends React.Component { constructor(props){ super(props); this.state = {number: 0}; } add = () => { this.setState({number: this.state.number+1}); this.setState({number: this.state.number+2}); console.log(this.state.number);//打印0 setTimeout(() => { console.log(this.state.number);//打印2 }) } render(){ return (<button onClick={this.add}></button>) } }
2) 理解上面流程了,就能理解爲何定時器中的setState看起來並非延遲執行。code
由於定時器到期前,整個流程已經跑完了,控制器處於關閉狀態,因此就當即更新state了; 即在setState源碼中,若控制器開啓,則須要入隊列;若控制器關閉,則不入隊列,當即執行;
this.setState({number: this.state.number+1}); this.setState({number: this.state.number+2}); this.setState({number: this.state.number+3}); setTimeout(()=>{ this.setState({number: this.state.number+4}); console.log(this.state);//打印7 }, 1000)
總之,setState有延遲/批量更新,是爲了節省渲染DOM的開銷,同時也保留了當即更新的功能隊列
ref的幾種用法
1) ref=字符串
不推薦,難以維護字符串
class Calculator extends React.Component { add = () => { let num1 = Number(this.refs.num1.value); let num2 = Number(this.refs.num2.value); this.refs.result.value = num1+num2 } render(){ return ( <div> <input ref="num1" /> + <input ref="num2" /> <button onClick={this.add}\>=</button\> <input ref="result" /> </div> ) } }
2) ref=函數
不推薦。函數在DOM渲染後執行,instance就是DOM元素的實例~~~~input
class Calculator extends React.Component { add = () => { let num1 = Number(this.num1.value); let num2 = Number(this.num2.value); this.result.value = num1+num2 } render(){ return ( <div> <input ref={instance=>this.num1=instance} /> + <input ref={instance=>this.num2=instance} /> <button onClick={this.add}>=</~~~~button> <input ref={instance=>this.result=instance} /> </div> ) } }
3)React.createRef
推薦寫法~~~~同步
class Calculator extends React.Component { constructor() { super(); this.num1 = React.createRef(); this.num2 = React.createRef(); this.result = React.createRef(); } add = () => { let num1 = Number(this.num1.current.value); let num2 = Number(this.num2.cu~~~~rrent.value); this.result.current.value = num1 + num2;~~~~ }; render() { return ( <div> <input ref={this.num1} /> + <input ref={this.num2} /> <button onClick={this.add}>=</button> <input ref={this.result} /> </div> ); } }