欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React this.setState方法使用原理分析介紹

 更新時(shí)間:2022年09月01日 14:38:53   作者:搞前端的小菜  
我們知道,在React中沒有像Vue那種數(shù)據(jù)雙向綁定的效果。而this.setState方法就是用來對數(shù)據(jù)進(jìn)行更改的。而通過this.setState方法更改的數(shù)據(jù),會讓組件的render重新渲染,并且刷新數(shù)據(jù)

摘要

這一篇文章,主要是簡單的實(shí)現(xiàn)一下this.setState方法,為了實(shí)現(xiàn)該方法,就要知道this.setState方法具有什么特點(diǎn)。

首先在React組件中,我們先定義一個(gè)state和setState方法:

  myState = {
    value: 0
  }
  mySetState = ( changeState ) =>{
    this.setState(
      this.myState
    )
  }

這里可能會說,為什么在自己寫的mySetState 方法里還要調(diào)用React的setState呢?都調(diào)用人家的了還算自己寫的嗎?

由于在React中,render只能處理通過setState方法修改的值,所以這里我們在mySetState 中調(diào)用了一下。但是mySetState方法的具體實(shí)現(xiàn)還是我們自己去完成。

1.異步的setState

首先,我們看一段代碼:

  state = {
    value: 0
  }
    setTimeout(() => {
      console.log('SetTimeOut ---- '+this.state.value);
    }, 0);
    new Promise((resolve,reject) => {
      resolve(this.state.value)
    })
    .then(res => {
      console.log('Promise ---- '+res);
    })
    this.setState({
      value: this.state.value+1
    })
    console.log(this.state.value);

這段代碼會輸出什么呢?

由這個(gè)結(jié)果我們可以知道上面的代碼執(zhí)行順序:

(1)console.log(this.state.value);

(2)Promise代碼

(3)setState方法

(4)setTimeOut方法

所以setState一定是一個(gè)異步的方法。

在實(shí)現(xiàn)的時(shí)候,要注意異步的問題。

2.多個(gè)setState方法

我們繼續(xù)看一段代碼:

    this.setState({
      value: this.state.value+1
    })
    this.setState({
      value: this.state.value+1
    })
    this.setState({
      value: this.state.value+1
    })
    this.setState({
      value: this.state.value+1
    })
    this.setState({
      value: this.state.value+1
    })
    setTimeout(() => {
      console.log(this.state.value);
    }, 0);

這段代碼輸出的會是1還是5呢?

答案是1,這是React為了效率所作的一個(gè)優(yōu)化。防止每次setState都會導(dǎo)致render重新渲染!

而如果我就想要這個(gè)效果,React也是提供了一個(gè)解決辦法,就是setState方法可以接受一個(gè)函數(shù)作為參數(shù):

    this.setState( (preState) => {
      return {
        value: preState.value+1
      }
    } )
    this.setState( (preState) => {
      return {
        value: preState.value+1
      }
    } )
    this.setState( (preState) => {
      return {
        value: preState.value+1
      }
    } )
    this.setState( (preState) => {
      return {
        value: preState.value+1
      }
    } )
    setTimeout(() => {
      console.log(this.state.value);
    }, 0);

preState代表的是上一個(gè)state。

3.手動(dòng)實(shí)現(xiàn)mySetState

OK,有了上面對setState方法分了解,我們可以手動(dòng)的實(shí)現(xiàn)一下mySetState方法

首先解決就是調(diào)用多個(gè)setState方法的時(shí)候,所以我們不能每次調(diào)用mySetState方法都讓state值更新,也就是這么寫:

  mySetState = ( changeState ) =>{
    Object.assign(this.myState,changeState)
    this.setState(
      this.myState
    )
  }

我們只需要知道最后一個(gè)changeState,所以這里我們維護(hù)一個(gè)隊(duì)列,用來保存所有的changeState,然后每次調(diào)用mySetState 方法的時(shí)候,將changeState放到隊(duì)列里面:

  queue = []
  mySetState = ( changeState ) =>{
    Promise.resolve().then(()=>{
      this.stateShift()
    })
    this.queue.push(changeState)
    this.setState(
      this.myState
    )
  }

重頭戲來了,我們已經(jīng)有了這個(gè)隊(duì)列,那我們是如何讓這個(gè)隊(duì)列的changeState 出來的呢?

這里我們寫一個(gè)方法:

  stateShift() {
    let empty;
    while(empty = this.queue.shift()){
    }
  }

通過迭代器的方式,遍歷隊(duì)列。empty就是拿到的每個(gè)changeState 。changeState 有兩種形式,對象的時(shí)候肯定是很好寫的。

  stateShift() {
    let empty;
    while(empty = this.queue.shift()){
      if(typeof empty === 'object'){
        Object.assign(this.myState,empty)
      }
  }

只需要讓新出來的去替換舊的就可以了。如果changeState 是一個(gè)方法,這個(gè)時(shí)候,我們需要手動(dòng)去維護(hù)一個(gè)preState變量,這個(gè)變量的作用就是用來保存上一個(gè)state。

所以具體的實(shí)現(xiàn)應(yīng)該為:

  stateShift() {
    let empty;
    while(empty = this.queue.shift()){
      if(!this.preState){
        this.preState =  Object.assign({},this.myState)
      }
      if(typeof empty === 'object'){
        Object.assign(this.myState,empty)
      }else if(typeof empty === 'function'){
        Object.assign(this.myState,empty(this.preState))
      }
      this.preState = this.myState
    }
  }

最后一步,這個(gè)方法應(yīng)該什么時(shí)候調(diào)用。其實(shí)需要注意的無非就是,要在所有的changeState 都放到隊(duì)列中,再進(jìn)行調(diào)用。

而this.queue.push(changeState)這段代碼又是同步的代碼,所以在它之前,通過異步的方式調(diào)用,就可以實(shí)現(xiàn)出這種效果:

  mySetState = ( changeState ) =>{
    Promise.resolve().then(()=>{
      this.stateShift()
    })
    this.queue.push(changeState)
    this.setState(
      this.myState
    )
  }

最后將整個(gè)實(shí)現(xiàn)代碼附上:

import React, { Component } from 'react'
export default class Child extends Component {
  state = {
    value: 0
  }
  myState = {
    value: 0
  }
  queue = []
  mySetState = ( changeState ) =>{
    Promise.resolve().then(()=>{
      this.stateShift()
    })
    this.queue.push(changeState)
    this.setState(
      this.myState
    )
  }
  stateShift() {
    let empty;
    while(empty = this.queue.shift()){
      if(!this.preState){
        this.preState =  Object.assign({},this.myState)
      }
      if(typeof empty === 'object'){
        Object.assign(this.myState,empty)
      }else if(typeof empty === 'function'){
        Object.assign(this.myState,empty(this.preState))
      }
      this.preState = this.myState
    }
  }
  add = ()=>{
    //測試代碼
    // this.mySetState( (pre) => {
    //   return {
    //     value: pre.value + 1
    //   }
    // } )
    // this.mySetState( (pre) => {
    //   return {
    //     value: pre.value + 1
    //   }
    // } )
    // this.mySetState( (pre) => {
    //   return {
    //     value: pre.value + 1
    //   }
    // } )
    // this.mySetState({
    //   value: this.myState.value+1
    // })
    // this.mySetState({
    //   value: this.myState.value+1
    // })
    // this.mySetState({
    //   value: this.myState.value+1
    // })
    // this.mySetState({
    //   value: this.myState.value+1
    // })
    setTimeout(() => {
      console.log('SetTimeOut ---- '+this.myState.value);
    }, 0);
    new Promise((resolve,reject) => {
      resolve(this.myState.value)
    })
    .then(res => {
      console.log('Promise ---- '+res);
    })
    this.mySetState({
      value: this.myState.value+1
    })
    console.log(this.myState.value);
  }
  render() {
    return (
      <div>
        <span>{this.myState.value}</span>
        <br></br>
        <button onClick={this.add}>++</button>
      </div>
    )
  }
}

最后值得注意的是,這里只是針對于setState的一些特點(diǎn)去模擬了一下setState的實(shí)現(xiàn),具體的源碼可能不會像這樣簡單!

到此這篇關(guān)于React this.setState方法使用原理分析介紹的文章就介紹到這了,更多相關(guān)React this.setState內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react腳手架如何配置less和ant按需加載的方法步驟

    react腳手架如何配置less和ant按需加載的方法步驟

    這篇文章主要介紹了react腳手架如何配置less和ant按需加載的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • React系列useSyncExternalStore學(xué)習(xí)詳解

    React系列useSyncExternalStore學(xué)習(xí)詳解

    這篇文章主要為大家介紹了React系列useSyncExternalStore的學(xué)習(xí)及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Remix如何支持原生?CSS方法詳解

    Remix如何支持原生?CSS方法詳解

    這篇文章主要為大家介紹了Remix如何支持原生CSS的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • React狀態(tài)管理器Rematch的使用詳解

    React狀態(tài)管理器Rematch的使用詳解

    rematch是對redux的二次封裝,簡化了redux是使用,極大的提高了開發(fā)體驗(yàn),這篇文章主要介紹了React狀態(tài)管理器Rematch的使用,需要的朋友可以參考下
    2022-09-09
  • React事件處理和表單的綁定詳解

    React事件處理和表單的綁定詳解

    這篇文章主要介紹了React事件處理和表單的綁定,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • React實(shí)現(xiàn)頁面狀態(tài)緩存(keep-alive)的示例代碼

    React實(shí)現(xiàn)頁面狀態(tài)緩存(keep-alive)的示例代碼

    因?yàn)?react、vue都是單頁面應(yīng)用,路由跳轉(zhuǎn)時(shí),就會銷毀上一個(gè)頁面的組件,但是有些項(xiàng)目不想被銷毀,想保存狀態(tài),本文給大家介紹了React實(shí)現(xiàn)頁面狀態(tài)緩存(keep-alive)的代碼示例,需要的朋友可以參考下
    2024-01-01
  • react項(xiàng)目引入antd框架方式以及遇到的一些坑

    react項(xiàng)目引入antd框架方式以及遇到的一些坑

    這篇文章主要介紹了react項(xiàng)目引入antd框架方式以及遇到的一些坑,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • React報(bào)錯(cuò)Too many re-renders解決

    React報(bào)錯(cuò)Too many re-renders解決

    這篇文章主要為大家介紹了React報(bào)錯(cuò)Too many re-renders解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • react中實(shí)現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示

    react中實(shí)現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示

    這篇文章主要介紹了react中實(shí)現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示,使用react實(shí)現(xiàn)要比js簡單很多,方法都是大同小異,具體實(shí)現(xiàn)代碼大家跟隨腳本之家小編一起看看吧
    2018-07-07
  • React父組件調(diào)用子組件中的方法實(shí)例詳解

    React父組件調(diào)用子組件中的方法實(shí)例詳解

    最近做一個(gè)React項(xiàng)目,所有組件都使用了函數(shù)式組件,遇到一個(gè)父組件調(diào)用子組件方法的問題,下面這篇文章主要給大家介紹了關(guān)于React父組件調(diào)用子組件中方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07

最新評論