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

React state狀態(tài)屬性詳細(xì)講解

 更新時間:2022年09月30日 09:32:01   作者:月光曬了很涼快  
React將組件(component)看成一個狀態(tài)機(jī)(State Machines),通過其內(nèi)部自定義的狀態(tài)(State)和生命周期(Lifecycle)實現(xiàn)并與用戶交互,維持組件的不同狀態(tài)

1. 基本使用

要點:

  1. 成員屬性 state 它是一個特殊的屬性,它是當(dāng)前類的私有數(shù)據(jù),只有在當(dāng)前的組件中才能操作里面的數(shù)據(jù)
  2. 狀態(tài)( state )即數(shù)據(jù),是組件內(nèi)部的私有數(shù)據(jù),只能在組件內(nèi)部使用,和vue中data差不多,不過它沒有像vue中的data進(jìn)行了數(shù)據(jù)劫持
  3. state的值是對象,表示一個組件中可以有多個數(shù)據(jù)
  4. 通過this.state來獲取狀態(tài),react 中沒有做數(shù)據(jù)代理
  5. 想要修改 state 數(shù)據(jù)值同時讓視圖更新則需要調(diào)用專用的方法 this.setState
  6. state 它是類的一個成員屬性
  7. state 中的數(shù)據(jù)可讀可寫的

使用:

import React, { Component } from 'react';
class App extends Component {
  // 初始化方式1
  // state = {
  //   num: 100
  // }
  // 初始化方式2
  constructor(props) {
    super(props);
    this.state = {
      num: 100
    }
  }
  addNum(evt, n = 1) {
    // 同步修改數(shù)據(jù),它不會觸發(fā)視圖更新
    this.state.num += n
    this.forceUpdate()
    console.log(this.state.num);
  }
  render() {
    return (
      <div>
        {/* 在視圖中讀取state中的數(shù)據(jù) */}
        <h3>{this.state.num}</h3>
        <button onClick={evt => this.addNum(evt, 2)}>累加</button>
      </div>
    );
  }
}
export default App;

2. 使用setState操作state數(shù)據(jù)

概述:

修改 state 中的 num 屬性數(shù)據(jù)的同時,讓視圖更新,用到專門用來修改 state 中數(shù)據(jù)的方法 setState。

語法:

# 語法1
this.setState({
    key:value
})
# 語法2  推薦
this.setState(state => {
    return {key:value}
})

使用:

import React, { Component } from 'react';
class App extends Component {
  state = {
    num: 100
  }
  addNum(evt, n = 1) {
    // 對象方式更新 批處理  => 數(shù)組【隊列】   虛擬dom比對
    // 它是一個異步操作
    this.setState({
      num: this.state.num + 1
    })
    console.log(this.state.num);
    // this.setState({
    //   num: this.state.num + 1
    // }, () => {
    //   // 回調(diào)函數(shù)中就可以得到最新的狀態(tài)數(shù)據(jù)
    //   console.log(this.state.num);
    // })
  }
  render() {
    return (
      <div>
        {/* 在視圖中讀取state中的數(shù)據(jù) */}
        <h3>{this.state.num}</h3>
        <button onClick={evt => this.addNum(evt, 2)}>累加</button>
      </div>
    );
  }
}
export default App;

注意:

注意執(zhí)行結(jié)果中,雖然視圖發(fā)生了更新,但是控制臺打印 state 中的數(shù)據(jù)并沒有發(fā)生改變,說明這里的更新數(shù)據(jù)是異步操作。

之所以是異步操作,是因為 React 在這里做了批處理。即當(dāng)執(zhí)行多次修改數(shù)據(jù)的操作時,React 并不會立即執(zhí)行,而是將這些操作存入一個異步隊列中,然后再進(jìn)行統(tǒng)一處理,這樣做可以提升性能。假如我現(xiàn)在要修改 3 次數(shù)據(jù),不用批處理需要更新視圖 3 次,而如果進(jìn)行批處理的話,只需要更新視圖一次。更新視圖需要進(jìn)行 dom 比對,只比 1 次顯然比比對 3 次性能更好。

關(guān)于 setState 方法(React 批處理)中的對象合并:

import React, { Component } from 'react';
class App extends Component {
  state = {
    num: 100
  }
  addNum(evt, n = 1) {
    this.setState({
      num: this.state.num + 1
    })
    this.setState({
      num: this.state.num + 2
    })
    this.setState({
      num: this.state.num + 3
    })
    console.log(this.state.num);
    // 函數(shù),它不會合并,它會依次執(zhí)行  == 建議多用函數(shù)方式,保證數(shù)據(jù)完整性
    // this.setState(state => ({
    //   num: state.num + 1
    // }))
    // this.setState(state => ({
    //   num: state.num + 2
    // }))
    // this.setState(state => ({
    //   num: state.num + 3
    // }))
    // console.log(this.state.num);//6
  }
  render() {
    return (
      <div>
        {/* 在視圖中讀取state中的數(shù)據(jù) */}
        <h3>{this.state.num}</h3>
        <button onClick={evt => this.addNum(evt, 2)}>累加</button>
      </div>
    );
  }
}
export default App;

從圖中運行結(jié)果可以看出,當(dāng)我們多次修改數(shù)據(jù)時,視圖只針對最后一次修改作出渲染。這是因為在 React 批處理中(批處理隊列是一個集合,這里看作是一個對象),會進(jìn)行對象合并。什么意思呢?首先對象的 key 值是唯一的,當(dāng) key 值 num 已經(jīng)存在時,再傳 num 會對對象中已經(jīng)存在的 num 進(jìn)行修改,即對象中有效的 num 的值是最后一次操作:this.state.num + 3。

補(bǔ)充說明:批處理隊列的底層進(jìn)行的是[...obj1,...obj2]的操作,所以重復(fù)的項只會出現(xiàn)一次。而函數(shù)方式的批處理進(jìn)行的是[fn1,fn2...],所以會依次執(zhí)行。這里的解釋過于牽強(qiáng)和抽象,只是為了簡單理解和記憶,更加完整的闡述需要了解底層之后,再加深理解。

關(guān)于 setState 方法的同步操作:

react17 及之前版本,如果你把當(dāng)前的操作不寫在合成事件中,則 setState 它就是同步的,react18全是異步的。

setState 在執(zhí)行的過程中,它會判斷當(dāng)?shù)膱?zhí)行環(huán)境,如果為宏任務(wù)等,則它會立即執(zhí)行。

也就是說, setState 方法只要寫在合成事件處理方法中,它就是異步的;只要不寫在合成事件中,它都是同步。(僅限于 react17 及之前版本)

比如 setState 方法寫在宏任務(wù)中或者寫在原生事件中就是同步的。

例如下面這樣的寫法就是同步操作:

import React, { Component } from 'react';
class App extends Component {
  // setState它是同步的也是異步的
  // 只要寫在合成事件處理方法中,它就是異步
  // 只要不寫在合成事件中,它都是同步
  state = {
    num: 100
  }
  addNum(evt, n = 1) {
    setTimeout(() => {
      // 寫在宏任務(wù)中的setState它是同步的
      this.setState({
        num: this.state.num + 3
      })
      console.log(this.state.num);
    }, 0);
  }
  // 類似于vue中的mounted方法
  // componentDidMount() {
  //   // 寫在原生事件中它的setState也是同步的
  //   // document.onclick = () => {
  //   //   this.setState({
  //   //     num: this.state.num + 3
  //   //   })
  //   //   console.log(this.state.num);
  //   // }
  // 
  render() {
    return (
      <div>
        {/* 在視圖中讀取state中的數(shù)據(jù) */}
        <h3>{this.state.num}</h3>
        <button onClick={evt => this.addNum(evt, 2)}>累加</button>
      </div>
    );
  }
}
export default App;

3. 案例-toDoList

import React, { Component } from 'react';
class App extends Component {
  state = {
    todos: []
  }
  onEnter = evt => {
    if (evt.keyCode === 13) {
      let title = evt.target.value.trim()
      // 方案1
      // let todos = this.state.todos.concat({ id: Date.now(), title, done: false })
      // this.setState({ todos })
      // 方案2
      // this.state.todos.push({ id: Date.now(), title, done: false })
      // this.forceUpdate() // 這里也可以寫成這一句:this.setState({})
      // 如果你setState寫了一個空對象,則它會更新視圖一次
      // this.setState({})
      // 如果你寫了為null,setState不會做任何事件,相當(dāng)于沒有調(diào)用
      // this.setState(null)
      // 方案3:更新數(shù)據(jù),推薦,確保數(shù)據(jù)的完整性
      this.setState(state => ({
        todos: [...state.todos, { id: Date.now(), title, done: false }]
      }), () => evt.target.value = '')
    }
  }
  del = tid => () => {
    this.setState(state => ({
      todos: state.todos.filter(({ id }) => id != tid)
    }))
  }
  delIndex = index => () => {
    this.state.todos.splice(index, 1)
    this.setState({})
  }
  render() {
    return (
      <div>
        <div>
          <input type="text" onKeyUp={this.onEnter} />
        </div>
        <hr />
        <ul>
          {
            this.state.todos.map((item, index) => (
              <li key={item.id}>
                <span>{item.title}</span>
                {/* 按 id 刪除 */}
                <span onClick={this.del(item.id)}>刪除</span>
                {/* 按索引刪除 */}
                <span onClick={this.delIndex(index)}>刪除</span>
              </li>
            ))
          }
        </ul>
      </div>
    );
  }
}
export default App;

注意:

setState 還有兩種擴(kuò)展用法:

如果你setState寫了一個空對象,則它會更新視圖一次

this.setState({})

如果你寫了為null,setState不會做任何事件,相當(dāng)于沒有調(diào)用

this.setState(null)

4. 案例-購物車

import React, { Component } from 'react';
class App extends Component {
  state = {
    carts: [
      { id: 1, name: '水果手機(jī)14', price: 1, num: 1 },
      { id: 2, name: '大米手機(jī)14', price: 1, num: 2 },
      { id: 3, name: '一般手機(jī)14', price: 1, num: 3 },
    ]
  }
  setNum = (n, index) => {
    // 方案1
    this.state.carts[index]['num'] += n
    if (this.state.carts[index]['num'] <= 1) this.state.carts[index]['num'] = 1
    if (this.state.carts[index]['num'] >= 5) this.state.carts[index]['num'] = 5
    this.setState({})
    // 方案2
    // this.setState(state => {
    //   state.carts[index]['num'] += n
    //   let carts = state.carts
    //   return { carts }// 同等于 return {carts:carts}
    // })
  }
  totalPrice = () => {
    return this.state.carts.reduce((p, c) => {
      p += c.num * c.price
      return p
    }, 0)
  }
  render() {
    return (
      <div>
        <table width='600' border='1'>
          <thead>
            <tr>
              <th>ID</th>
              <th>名稱</th>
              <th>價格</th>
              <th>數(shù)量</th>
            </tr>
          </thead>
          <tbody>
            {
              this.state.carts.map((item, index) => (
                <tr key={item.id}>
                  <td>{item.id}</td>
                  <td>{item.name}</td>
                  <td>{item.price}</td>
                  <td>
                    <button onClick={() => this.setNum(-1, index)}>---</button>
                    <span>{item.num}</span>
                    <button onClick={() => this.setNum(1, index)}>+++</button>
                  </td>
                </tr>
              ))
            }
          </tbody>
        </table>
        <hr />
        <h3>{this.totalPrice()}</h3>
      </div>
    );
  }
}
export default App;

到此這篇關(guān)于React state狀態(tài)屬性詳細(xì)講解的文章就介紹到這了,更多相關(guān)React state狀態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React組件創(chuàng)建與事件綁定的實現(xiàn)方法

    React組件創(chuàng)建與事件綁定的實現(xiàn)方法

    react事件綁定時。this并不會指向當(dāng)前DOM元素。往往使用bind來改變this指向,今天通過本文給大家介紹React事件綁定的方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • React使用useEffect解決setState副作用詳解

    React使用useEffect解決setState副作用詳解

    這篇文章主要為大家介紹了React使用useEffect解決setState副作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • react實現(xiàn)移動端下拉菜單的示例代碼

    react實現(xiàn)移動端下拉菜單的示例代碼

    這篇文章主要介紹了react實現(xiàn)移動端下拉菜單的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 詳解React中共享組件邏輯的三種方式

    詳解React中共享組件邏輯的三種方式

    這篇文章主要介紹了詳解React中共享組件邏輯的三種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • React條件渲染實例講解使用

    React條件渲染實例講解使用

    在React中,你可以創(chuàng)建不同的組件來封裝各種你需要的行為。然后還可以根據(jù)應(yīng)用的狀態(tài)變化只渲染其中的一部分。React 中的條件渲染和JavaScript中的一致,使用JavaScript操作符if或條件運算符來創(chuàng)建表示當(dāng)前狀態(tài)的元素,然后讓React根據(jù)它們來更新UI
    2022-11-11
  • nodejs和react實現(xiàn)即時通訊簡易聊天室功能

    nodejs和react實現(xiàn)即時通訊簡易聊天室功能

    這篇文章主要介紹了nodejs和react實現(xiàn)即時通訊簡易聊天室功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • 淺談對于react-thunk中間件的簡單理解

    淺談對于react-thunk中間件的簡單理解

    這篇文章主要介紹了淺談對于react-thunk中間件的簡單理解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 使用react-native-image-viewer實現(xiàn)大圖預(yù)覽

    使用react-native-image-viewer實現(xiàn)大圖預(yù)覽

    這篇文章主要介紹了使用react-native-image-viewer實現(xiàn)大圖預(yù)覽,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • React數(shù)據(jù)傳遞之組件內(nèi)部通信的方法

    React數(shù)據(jù)傳遞之組件內(nèi)部通信的方法

    這篇文章主要介紹了React數(shù)據(jù)傳遞之組件內(nèi)部通信的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • 淺談react-router@4.0 使用方法和源碼分析

    淺談react-router@4.0 使用方法和源碼分析

    這篇文章主要介紹了淺談react-router@4.0 使用方法和源碼分析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06

最新評論