日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React?State與生命周期詳細介紹_React

作者:小綿楊Yancy ? 更新時間: 2022-10-27 編程語言

一、State

在React當中,當你更新組件的state,然后新的state就會重新渲染到頁面中。在這個時候不需要你操作任何DOM。這和vue中組件的data中的數據是相似的。

1.1 類組件中的State

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>State</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生產環境中不建議使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      class Clock extends React.Component {
        constructor(props) {
          super(props);
          this.state = { title: "React State", date: new Date() };
          this.handleClick = this.handleClick.bind(this);
        }
        handleClick() {
          this.setState({ date: new Date() });
        }
        render() {
          return (
            <div>
              <p>{this.state.title}</p>
              <p>現在是 {this.state.date.toLocaleTimeString()}.</p>
              <button onClick={this.handleClick}>更新時間</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

類組件需要在constructor中定義this.state對象,其對應的屬性就是需要使用的state,例如上面代碼中的title和date屬性,在render函數中通過this.sate.XXX調用。

注意,修改state需要調用this.setState方法,不可以直接對state進行賦值。

這里的handleClick是按鈕的點擊事件,點擊按鈕后,調用setState方法重新為date賦值,此時頁面會自動更新。

1.2 函數組件中的State

函數組件沒有state => React v16.8.0推出Hooks API,其中的一個API叫做useState可以解決問題。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>State</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生產環境中不建議使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      const Clock = (props) => {
        const [n, setN] = React.useState(0);
        function addNum() {
          setN(n + 1);
        }
        return (
          <div>
            <p>現在的n是 {n} .</p>
            <button onClick={addNum}>n+1</button>
          </div>
        );
      };
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

可以看到,在函數組件中使用state需要借助useState,并且useState會返回setXXX方法用于修改定義的state,相比于類組件,函數組件更加簡潔,而且不用關注修改state時的this指向問題。

二、React生命周期

組件的生命周期可分成三個狀態:

  • Mounting(掛載):已插入真實 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸載):已移出真實 DOM

2.1 掛載

當組件實例被創建并插入 DOM 中時,其生命周期調用順序如下:

  1. constructor(): 在 React 組件掛載之前,會調用它的構造函數。
  2. getDerivedStateFromProps():在調用 render 方法之前調用,并且在初始掛載及后續更新時都會被調用。
  3. render(): render() 方法是 class組件中唯一必須實現的方法。
  4. componentDidMount(): 在組件掛載后(插入 DOM 樹中)立即調用。

render() 方法是 class 組件中唯一必須實現的方法,其他方法可以根據自己的需要來實現。

2.2 更新

每當組件的 state 或 props 發生變化時,組件就會更新。

當組件的 props 或 state 發生變化時會觸發更新。組件更新的生命周期調用順序如下:

  1. getDerivedStateFromProps(): 在調用 render 方法之前調用,并且在初始掛載及后續更新時都會被調用。根據shouldComponentUpdate() 的返回值,判斷 React 組件的輸出是否受當前 state 或 props更改的影響。
  2. shouldComponentUpdate():當 props 或 state 發生變化時,shouldComponentUpdate() 會在渲染執行之前被調用。
  3. render(): render() 方法是 class 組件中唯一必須實現的方法。
  4. getSnapshotBeforeUpdate(): 在最近一次渲染輸出(提交到 DOM節點)之前調用。
  5. componentDidUpdate(): 在更新后會被立即調用。

render() 方法是 class 組件中唯一必須實現的方法,其他方法可以根據自己的需要來實現。

2.3 卸載

當組件從 DOM 中移除時會調用如下方法:

componentWillUnmount(): 在組件卸載及銷毀之前直接調用。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lifecycle</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生產環境中不建議使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      class Button extends React.Component {
        constructor(props) {
          super(props);
          this.state = { data: 0 };
          this.setNewNumber = this.setNewNumber.bind(this);
        }
        setNewNumber() {
          this.setState({ data: this.state.data + 1 });
        }
        render() {
          return (
            <div>
              <button onClick={this.setNewNumber}>INCREMENT</button>
              <Content myNumber={this.state.data}></Content>
            </div>
          );
        }
      }
      class Content extends React.Component {
        componentWillMount() {
          console.log("Component WILL MOUNT!");
        }
        componentDidMount() {
          console.log("Component DID MOUNT!");
        }
        componentWillReceiveProps(newProps) {
          console.log("Component WILL RECEIVE PROPS!");
        }
        shouldComponentUpdate(newProps, newState) {
          return true;
        }
        componentWillUpdate(nextProps, nextState) {
          console.log("Component WILL UPDATE!");
        }
        componentDidUpdate(prevProps, prevState) {
          console.log("Component DID UPDATE!");
        }
        componentWillUnmount() {
          console.log("Component WILL UNMOUNT!");
        }
        render() {
          return (
            <div>
              <h3>{this.props.myNumber}</h3>
            </div>
          );
        }
      }
      ReactDOM.render(
        <div>
          <Button />
        </div>,
        document.getElementById("app")
      );
    </script>
  </body>
</html>

注意:只有類組件才有生命周期。函數組件每次都是重新運行函數,舊的組件即刻被銷毀。

2.4 函數式組件useEffect

與使用state需要借助useState一樣,在函數組件中,我們需要借助可以借助react提供的方法在函數式組件中實現“生命周期”,它就是useEffect

useEffect 給函數組件增加了操作副作用的能力。它跟 class 組件中的

componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不過被合并成了一個 API。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>useEffect</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生產環境中不建議使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      const Clock = (props) => {
        const [n, setN] = React.useState(0);
        function addNum() {
          setN(n + 1);
        }
        React.useEffect(() => {
          console.log(n);
        });
        return (
          <div>
            <p>現在的n是 {n} .</p>
            <button onClick={addNum}>n+1</button>
          </div>
        );
      };
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

可以看到,上面的使用useEffect時,掛載或者銷毀時,都會觸發useEffect中的函數,那么如何使用useEffect模擬生命周期呢?

//    只在組件掛載后顯示,只需要加個空數組做參數即可
    useEffect(() => {
        document.title = `You clicked ${count} times`;
    },[]);
//    銷毀階段
    useEffect(() => {
        return ()=>{
				console.log("銷毀階段")
			}
    });

三、總結

可以看到,類組件和函數組件在State和生命周期上區別還是非常大的,函數式組件需要調用react提供的hooks(鉤子函數,非常重要,后面會專門學習)來實現類組件對于的功能。

學習過程中,我發現react類組件類似于vue2的選項式api組件,而函數組件則vue3組合式api十分相似。

原文鏈接:https://blog.csdn.net/ZHANGYANG_1109/article/details/125885933

欄目分類
最近更新