首頁 > 軟體

react中context傳值和生命週期詳解

2023-03-19 06:02:04

假設:

專案中存在複雜元件樹:

context傳值用途

資料是通過 props 屬性自上而下(由父及子)進行傳遞的,但這種做法對於某些型別的屬性而言是極其繁瑣的(例如:地區偏好,UI 主題),這些屬性是應用程式中許多元件都需要的。

Context傳值優點

Context 提供了一種在元件之間共用此類值的方式,而不必顯式地通過元件樹的逐層傳遞 props。

何時使用 Context

Context 設計目的是為了共用那些對於一個元件樹而言是“全域性”的資料,例如當前認證的使用者、主題或首選語言。

ContextAPI

1.React.createContext API 
功能:
建立一個 Context 物件。
//程式碼
//建立context物件的
import React from 'react'
let context=React.createContext();
export default context;
 
2.Context.Provider API
功能:
Provider 是context物件提供的內建元件  限定在某個作用域中使用context傳值。
限定作用域傳值。
 
3.Context.Consumer
context物件的內建元件
<MyContext.Consumer>
  {value => /* 基於 context 值進行渲染*/}
</MyContext.Consumer>
作用:監聽訂閱的context變更, 
這個函數接收當前的 context 值,返回一個 React 節點。

專案案例:主題色切換。

1.建立context.js檔案
  建立context物件  用來做context傳值。
//建立context物件的
import React from 'react'
export default React.createContext();
2。使用context找到限定範圍使用內建元件Provider
 {/* 使用Provider 內建元件限定context範圍 */}
 {/* value 必填  context傳遞的值 */}
        <ThemeContext.Provider>
          <div className="Admin">
            <div className="LeftMenu">
              <LeftMenu></LeftMenu>
            </div>
            <div className="RightContent">
              <div className="RightContent-top">
                <TopHeader></TopHeader>
              </div>
              <div className="RightContent-bottom">
                <Dashborder></Dashborder>
              </div>
            </div>
</ThemeContext.Provider>

瀏覽器報錯:

3.在使用context的元件中進行訂閱
左側選單元件
import React, { Component } from "react";
console.log(Component);
//引入context物件
import ThemeContext from "../components/context";
class LeftMenu extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      <>
        <div>左側選單</div>
      </>
    );
  }
}
//class類元件存在contextType  繫結context物件
LeftMenu.contextType = ThemeContext;

元件中繫結context之後使用:

意味著訂閱context元件的內部使用this.context獲取。

render() {
    //獲取context
    let theme = this.context;
    return (
      <>
        <div className={theme}>左側選單</div>
      </>
    );
  }

固定主體修改為動態主體

修改了context檔案程式碼
//定義預設主體色
 
export const themes = {
  dark: {
    backgroundColor: "#000",
    color: "#fff",
  },
  light: {
    backgroundColor: "#fff",
    color: "#000",
  },
};
 
//建立context物件的
import React from "react";
export const ThemeContext = React.createContext();
app.js檔案中獲取主題,動態切換主題。使用主題變數
constructor(props) {
    super(props);
    this.state = {
      //將固定的主體設定為state狀態
      themeType: "dark",//控制主體切換
      nowTheme: themes["dark"],//獲取當前預設主體
    };
  }
  render() {
    //解構獲取
    let { nowTheme } = this.state;
    return (
      <>
        {/* 使用Provider 內建元件限定context範圍 */}
        {/* value 必填  context傳遞的值 */}
        <ThemeContext.Provider value={nowTheme}>

訂閱元件中使用this.context獲取訂閱

render() {
    //獲取context
    let { backgroundColor, color } = this.context;
    return (
      <>
      //直接繫結行內css
        <div style={{ backgroundColor: backgroundColor, color: color }}>
          左側選單
        </div>
      </>
    );
  }

使用者點選其他元件修改主題的按鈕來變更主題

注意:不能直接使用this.context修改變數值
//可以在provider元件上 value中攜帶修改函數傳遞。在訂閱元件中獲取修改方法,執行反向傳遞值。
//修改主題變數方法
  changeTheme(type) {
    console.log("測試", type);
    this.setState({ themeType: type, nowTheme: themes[type] });
  }
  render() {
    //解構獲取
    let { nowTheme } = this.state;
    return (
      <>
        {/* 使用Provider 內建元件限定context範圍 */}
        {/* value 必填  context傳遞的值 */}
        <ThemeContext.Provider
          value={{ ...nowTheme, handler: this.changeTheme.bind(this) }}
        >
          <div className="Admin">
            <div className="LeftMenu">
              <LeftMenu></LeftMenu>
            </div>
            <div className="RightContent">
              <div className="RightContent-top">
                <TopHeader></TopHeader>
              </div>
              <div className="RightContent-bottom">
                <Dashborder></Dashborder>
              </div>
            </div>
          </div>
        </ThemeContext.Provider>
      </>
    );
 //在訂閱元件中直接使用
 //修改主題的方法
  change(themeType) {
    console.log(themeType);
    //獲取provider傳遞方法
    let { handler } = this.context;
    handler(themeType);
  }
  render() {
    let { themeButton } = this.state;
    return (
      <>
        <div>
          <span>主題色:</span>
          <div>
            {/* 控制左側選單和上header背景色 */}
            {themeButton.map((item, index) => {
              return (
                <button key={index} onClick={this.change.bind(this, item.type)}>
                  {item.name}
                </button>
              );
            })}
          </div>
        </div>
      </>
    );

新增自定義顏色

 {/* 顏色選擇器 */}
          背景色:
          <input
            type="color"
            name="selectbgColor"
            value={selectbgColor}
            onChange={this.changeColor.bind(this)}
          />
          字型色:
          <input
            type="color"
            name="selectColor"
            value={selectColor}
            onChange={this.changeColor.bind(this)}
          />
          <button onClick={this.yesHandler.bind(this)}>確認</button>
   //程式碼區域操作事件向父級傳遞引數
     //確認修改
  yesHandler() {
    let { myhandler } = this.context;
    let { selectbgColor, selectColor } = this.state;
    console.log(selectbgColor, selectColor);
    myhandler(selectbgColor, selectColor);
  }

新增監聽context變化

 {/*監聽context value值*/}
          <ThemeContext.Consumer>
            {(value) => {
              let { backgroundColor, color } = value;
              return (
                <>
                  <span>背景色:{backgroundColor}</span>
                  <span>文字色:{color}</span>
                </>
              );
            }}
          </ThemeContext.Consumer>

類元件的生命週期

元件生命週期解釋:元件初始化到銷燬整個過程。

生命週期三類:

  • Mounting(掛載):已插入真實 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(解除安裝):已移出真實 DOM
第一個階段:
程式碼演示第一個階段初始化掛載階段
import React, { Component } from "react";
 
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    console.log("初始化");
  }
  componentDidMount() {
    console.log("掛載完成");
  }
  render() {
    console.log("渲染");
    return (
      <>
        <div>測試</div>
      </>
    );
  }
}
 
export default App;

新增了掛載之前週期

 UNSAFE_componentWillMount() {
    console.log("掛載之前");
  }
 //18.x 版本中UNSAFE_ 字首

第二個階段:更新階段
能觸發類元件更新  props state

新增了更新之前週期

componentWillUpdate() {
    console.log("更新之前");
}

第三階段解除安裝:

 //解除安裝週期
  componentWillUnmount() {
    console.log("元件解除安裝");
  }

常用週期:

測試完成之後:18版本直接使用週期以上三個。

react推薦網路請求在componentDidMount
解除安裝清除副作用   componentWillUnmount

確認當前元件是否更新週期

//確認是否更新週期
  //必須帶返回值  true  false
  //提升效能
  shouldComponentUpdate(nextProps, nextState, nextContext) {
    console.log(nextProps);
    if (nextProps.name == this.props.name) return false;
    else return true;
  }
  不寫該週期預設是執行更新
1.componentWillMount() - 在染之前執行,在使用者端和伺服器端都會執行.
2.componentDidMount() - 是掛在完成之後執行一次
3.componentWillReceiveProps() - 當從父類別接收到 props 並且在呼叫另一個渲染器器之前呼叫。4.shouldComponentUpdatel) -根據特定條件返回 true 或 false如果你希望更新元件,請返回true 否則返它返回 false。
5.componentWillUpdate() - 是當前元件state和props發生變化之前執行
6.componentDidUpdate()-是當前元件state和props發生變化執行
7.componentWillUnmount0) - 從 DOM 解除安裝元件後呼叫。用於清理記憶體空間

到此這篇關於react中context傳值和生命週期的文章就介紹到這了,更多相關react context傳值和生命週期內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com