簡單聊下 React 中祖孫級元件之間的通訊方式
阿新 • • 發佈:2021-12-17
介紹
本文主要通過兩種方式實現,一是通過 components,一是通過 hooks,通過 cdn 方式引入,閱讀大概需要 7-8 min。
hooks 實現需要 react 版本在 16.8 以上
準備
- react.development.js 檔案 - 用於操作 React 相關 api
- react-dom.development.js 檔案 - 用於把 React 元件渲染成 DOM
- 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,下面說下祖孫級傳參的具體實現的幾個核心點
- 引入 React.createContext 變數
- 解構出 Provider、Consumer
- 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 存在的意義,它解決了哪些問題:
- 簡化了 class 形式建立元件的程式碼量
- 允許函式式元件使用 class 元件的狀態和生命週期
- 可拆分為更細粒度的函式,更方便複用
簡單說下它如何使用:
- 把上面的 class 元件全部改為 函式元件
- 引入 Context 變數的流程不變
- 變的只有在具體的子元件引用時的寫法,去除了必須宣告 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 就好
最後
稍微加了點粉色,最終實現效果皆為如下: