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> ); } }