1. 程式人生 > 其它 >簡單聊下 React 中祖孫級元件之間的通訊方式

簡單聊下 React 中祖孫級元件之間的通訊方式

介紹

本文主要通過兩種方式實現,一是通過 components,一是通過 hooks,通過 cdn 方式引入,閱讀大概需要 7-8 min。

hooks 實現需要 react 版本在 16.8 以上

準備

  1. react.development.js 檔案 - 用於操作 React 相關 api
  2. react-dom.development.js 檔案 - 用於把 React 元件渲染成 DOM
  3. babel.min.js 檔案 - 用於把 jsx 語法轉化為 js

具體實現如下:如果沒有可方便去 react_extends 專案 grandson_communication 分支 上檢視,專案程式碼都附屬到上面了

<script src="../js/17.0.1/react.development.js"></script>
<script src="../js/17.0.1/react-dom.development.js"></script>
<script src="../js/17.0.1/babel.min.js"></script>

<script type="text/babel">
// some js
</script>

方式一:components 實現

基本準備如下:

點選檢視程式碼
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Components</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="../js/17.0.1/react.development.js"></script>
    <script src="../js/17.0.1/react-dom.development.js"></script>
    <script src="../js/17.0.1/babel.min.js"></script>

    <script type="text/babel">
      class Father extends React.Component {
        render() {
          return (
            <div>
              father <ChildA />
            </div>
          )
        }
      }

      class ChildA extends React.Component {
        render() {
          return (
            <div>
              ChildA <ChildB />
            </div>
          )
        }
      }

      class ChildB extends React.Component {
        render() {
          return (
            <div>
              ChildB <ChildC />
            </div>
          )
        }
      }

      class ChildC extends React.Component {
        render() {
          return <div>ChildC</div>
        }
      }

      ReactDOM.render(<Father />, document.getElementById('root'))
    </script>
  </body>
</html>

這裡實現了幾個元件的逐級巢狀,依次是 Father > ChildA > ChildB > ChildC,下面說下祖孫級傳參的具體實現的幾個核心點

  1. 引入 React.createContext 變數
  2. 解構出 Provider、Consumer
  3. Provider 包裹子元件,並通過 value 屬性傳入需要傳遞的引數

這裡的 Provider 和 Consumer 都是 Context 下的元件,想要具體瞭解的小夥伴可 翻閱官網 Context,推薦直接看下面程式碼,簡潔明瞭。
如果使用了 Provider,那麼 value 屬性一定要傳

具體實現:

點選檢視程式碼
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Components</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="../js/17.0.1/react.development.js"></script>
    <script src="../js/17.0.1/react-dom.development.js"></script>
    <script src="../js/17.0.1/babel.min.js"></script>

    <script type="text/babel">
      const myComponentContent = React.createContext() // 引入 context 變數
      const { Provider, Consumer } = myComponentContent // 解構出對應的元件

      class Father extends React.Component {
        render() {
          return (
            <div>
              father
              <Provider value={{ id: 1, name: 'zxn', text: '我是一段文字' }}>
                <ChildA />
              </Provider>
            </div>
          )
        }
      }

      class ChildA extends React.Component {
        static contextType = myComponentContent
        render() {
          const { id, name, text } = this.context
          return (
            <div>
              ChildA
              <div>
                我是從 Father 元件引入的變數,分別是 id: {id}、name: {name}
                、text:{text}
              </div>
              <ChildB />
            </div>
          )
        }
      }

      class ChildB extends React.Component {
        static contextType = myComponentContent
        render() {
          const { id } = this.context
          return (
            <div>
              ChildB
              <div>我是從 Father 元件引入的變數,我只用了 id: {id}</div>
              <ChildC />
            </div>
          )
        }
      }

      class ChildC extends React.Component {
        render() {
          return (
            <div>
              ChildC
              <Consumer>
                {(value) => {
                  return (
                    <div>
                      我是從 Father 元件引入的變數,我採用了回撥形式,我只用了
                      name: {value.name}
                    </div>
                  )
                }}
              </Consumer>
            </div>
          )
        }
      }

      ReactDOM.render(<Father />, document.getElementById('root'))
    </script>
  </body>
</html>

方式二:hooks 實現

簡單說下 hooks 存在的意義,它解決了哪些問題:

  1. 簡化了 class 形式建立元件的程式碼量
  2. 允許函式式元件使用 class 元件的狀態和生命週期
  3. 可拆分為更細粒度的函式,更方便複用

簡單說下它如何使用:

  1. 把上面的 class 元件全部改為 函式元件
  2. 引入 Context 變數的流程不變
  3. 變的只有在具體的子元件引用時的寫法,去除了必須宣告 static 靜態方法的步驟

具體實現:

點選檢視程式碼
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hooks</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="../js/17.0.1/react.development.js"></script>
    <script src="../js/17.0.1/react-dom.development.js"></script>
    <script src="../js/17.0.1/babel.min.js"></script>

    <script type="text/babel">
      const myComponentContent = React.createContext() // 引入 context 變數
      const { Provider, Consumer } = myComponentContent // 結構出對應的元件

      function Father() {
        return (
          <div>
            father
            <Provider value={{ id: 1, name: 'zxn', text: '我是一段文字' }}>
              <ChildA />
            </Provider>
          </div>
        )
      }

      function ChildA() {
        const { id, name, text } = React.useContext(myComponentContent)
        return (
          <div>
            ChildA
            <div>
              我是從 Father 元件引入的變數,分別是 id: {id}、name: {name}
              、text:{text}
            </div>
            <ChildB />
          </div>
        )
      }

      function ChildB() {
        const { id } = React.useContext(myComponentContent)
        return (
          <div>
            ChildB
            <div>我是從 Father 元件引入的變數,我只用了 id: {id}</div>
            <ChildC />
          </div>
        )
      }

      function ChildC() {
        return (
          <div>
            ChildC
            <Consumer>
              {(value) => {
                return (
                  <div>
                    我是從 Father 元件引入的變數,我採用了回撥形式,我只用了
                    name: {value.name}
                  </div>
                )
              }}
            </Consumer>
          </div>
        )
      }

      ReactDOM.render(<Father />, document.getElementById('root'))
    </script>
  </body>
</html>

這裡要注意下,使用函式式元件的時候,render 就不需要了,直接 return 就好

最後

稍微加了點粉色,最終實現效果皆為如下: