欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STATE

程序员文章站 2024-03-13 16:22:09
...

state

import React, { Component } from 'react';

class Count extends Component{
	 constructor(props){
	 	super(props);
	 	this.state={count:0};
	 	this.increase=this.increase.bind(this);
	 	this.decrease=this.decrease.bind(this)
	 	this.add=this.add.bind(this)
	 }
	 
	 add(){
	 	this.state.count=this.state.count+1
	 	console.log(this.state.count)
			
	 }

	 increaseSelf(){
	 	for(let i=0;i<1000;i++){
	 		console.log(i)
	 		this.setState({
	 		count:this.state.count+1
	 	})
	 	}
	 }

	 increase(){
		this.setState({
			count:this.state.count+1
	 	})
	 }

	 decrease(){
	 	this.setState({
	 		count:this.state.count-1
	 	})
	 }
	 
	 render(){
	 	console.log('********组件渲染*********')
	 	return(
	 		<div style={{margin:"100px"}}>
		 		<span>{this.state.count}</span>
		 		<button onClick={this.add}>add</button>
		 		<button onClick={this.increase}>increase</button>
		 		<button onClick={this.increase}>decrease</button>
	 		</div>
	 	)
	 }
}

class App extends Component {
  render() {
    return (
      <Count/>
    );
  }
}

export default App;

1.直接修改state,点击add按钮5次,依次打印1,2,3,4,5,但是页面上显示仍然是0,虽然修改了state,但不会渲染组件。

2.点击add按钮5次,一次打印1,2,3,4,5,页面上显示仍然是0,此时点击increase按钮,页面数字变成6.

修改increase()函数

	 increase(){
		this.setState({
			count:this.state.count+1
	 	})
		this.setState({
	 		count:this.state.count+2
	 	})
	 	this.setState({
	 		count:this.state.count+3
	 	})
	 
	 }

点击increase按钮,页面数字变成3。这是因为当前state.count的值是0,执行第一个setState()函数,将{count:0+1}映射到待执行队列,执行第二个setState()函数,将{count:0+2}映射到待执行队列,后执行的setState将覆盖掉前面的,最后一个是有效的。待执行队列中的count的值是3,执行更新。

如果改变三个setState()函数的顺序,最后一个有效。下列代码点击increase按钮,数字变成2

increase(){
		this.setState({
			count:this.state.count+1
	 	})
		
	 	this.setState({
	 		count:this.state.count+3
	 	})
	 	this.setState({
	 		count:this.state.count+2
	 	})

修改increase()函数,点击increase按钮,数字变成6,执行前三个setState()函数时,最后一个有效,待执行队列中的count的值是3,当setState的参数是函数时,prevState的值从待执行队列中取得,所以最终结果是6。

	 increase(){
		this.setState({
			count:this.state.count+1
	 	})
	 	
	 	this.setState({
	 		count:this.state.count+2
	 	})
	 	this.setState({
	 		count:this.state.count+3
	 	})
	 	this.setState((prevState, props)=>{return{count:prevState.count+1}})
	 	this.setState((prevState, props)=>{return{count:prevState.count+1}})
	 	this.setState((prevState, props)=>{return{count:prevState.count+1}})

	 
	 }

修改increase()函数,每点击一次,数字加1,不管点击速度有多快

	 increase(){
		this.setState({
			count:this.state.count+1
	 	})
	 }

修改increase()函数

	 increase(){
		this.increaseSelf()
	 }

从上面的两种情况可以猜测,待执行队列的执行时机,根据用户的行为,用户的一次操作,可能执行很多setState()函数,但是执行队列只执行一次。

 

修改increase()函数,点击increase按钮,数字变成2,setTimeout()也可以执行一次待执行队列(本质是setTimeout执行时,isBatchingUpdates是false)。实际上执行了两次render()函数。

	 increase(){
		this.setState({
	 		count:this.state.count+1
	 	})
		setTimeout(()=>this.setState({
	 		count:this.state.count+1
	 	}),0)
	 }

修改increase()函数,点击increase按钮,数字变成2,setTimeout()函数中的所有setState()都是同步执行,本质是isBatchingUpdates的值是false。

	 increase(){
		setTimeout(()=>{
			this.setState({
	 			count:this.state.count+1
	 		});
			this.setState({
	 			count:this.state.count+1
	 		});
		},0)
	 }

replaceState()和setState()的区别

比如现在state的结构是

state={
 name:"Jack"
 age:18
}

执行setState({name:"Tom"}),后

state={
 name:"Tom"
 age:18
}

如果执行的是replaceState({name:"Tom"})

state={
 name:"Tom"
}

react中的事件是合成事件。其中就有事务对事件函数进行封装。

function method(){
    console.log('111')
};
transaction.perform(method);
//执行initialize方法
//输出'111'
//执行close方法

 

**************************************************************************************************************

1.执行dispatchInteractiveEvent,此时isBatchingUpdates的值是false

function dispatchInteractiveEvent(topLevelType, nativeEvent) {
  console.log('dispatchInteractiveEvent',isBatchingUpdates)//dispatchInteractiveEvent false
  interactiveUpdates(dispatchEvent, topLevelType, nativeEvent);
}

2._interactiveUpdates函数就是interactiveUpdates$1函数

function interactiveUpdates(fn, a, b) {
  return _interactiveUpdates(fn, a, b);
}

3.此时isBatchingUpdates的值是false,执行performWork(),isBatchingUpdates = true;finally最后执行,将isBatchingUpdates变成false,执行performSyncWork();更新内容。

function interactiveUpdates$1(fn, a, b) {
  console.log('interactiveUpdates$1函数',isBatchingUpdates);//false
  console.log(isBatchingInteractiveUpdates);//false
  if (isBatchingInteractiveUpdates) {
    return fn(a, b);
  }
  // If there are any pending interactive updates, synchronously flush them.
  // This needs to happen before we read any handlers, because the effect of
  // the previous event may influence which handlers are called during
  // this event.
  if (!isBatchingUpdates && !isRendering && lowestPendingInteractiveExpirationTime !== NoWork) {
    // Synchronously flush pending interactive updates.
    performWork(lowestPendingInteractiveExpirationTime, false, null);
    lowestPendingInteractiveExpirationTime = NoWork;
  }
  var previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
  var previousIsBatchingUpdates = isBatchingUpdates;
  isBatchingInteractiveUpdates = true;
  isBatchingUpdates = true;
  try {
    return fn(a, b);
  } finally {
    isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
    isBatchingUpdates = previousIsBatchingUpdates;
    if (!isBatchingUpdates && !isRendering) {
      performSyncWork();
    }
  }
}

4.  dispatchEvent()调用batchedUpdates(),isBatching开始是false,执行_batchedUpdates()

var isBatching = false;
function batchedUpdates(fn, bookkeeping) {
  console.log(isBatching);//false
  console.log(isBatchingUpdates);//true
  if (isBatching) {
    // If we are currently inside another batch, we need to wait until it
    // fully completes before restoring state.
    return fn(bookkeeping);
  }
  isBatching = true;
  try {
    return _batchedUpdates(fn, bookkeeping);
  } finally {
    // Here we wait until all updates have propagated, which is important
    // when using controlled components within layers:
    // https://github.com/facebook/react/issues/1698
    // Then we restore state of any controlled component.
    isBatching = false;
    var controlledComponentsHavePendingUpdates = needsStateRestore();
    if (controlledComponentsHavePendingUpdates) {
      // If a controlled event was fired, we may need to restore the state of
      // the DOM node back to the controlled value. This is necessary when React
      // bails out of the update without touching the DOM.
      _flushInteractiveUpdates();
      restoreStateIfNeeded();
    }
  }
}

经过一系列函数调用执行incease()函数,执行setState()函数

Component.prototype.setState = function (partialState, callback) {
  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : void 0;
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};