摘要:可以看到,父級更新了,子組件也同步更新了,也就完成了父組件向子組件發起通信的目的。當然我們也可以通過適當的組件設計來避免過深的組件嵌套通信。所以這就解決了遠程組件通信深度組件嵌套的問題。組件間通信可以選擇像這樣的庫來處理。
0x000 概述
這一章講組件間通信,組件通信分為很多種:
父組件向子組件發起通信
子組件向父組件發起通信
兄弟組件間通訊
遠程組件通信
在組件通信中,有一種錯誤的說法,那就是父組件調用子組件,子組件調用父組件,這種說法其實是錯誤的,并沒有什么父組件調用子組件,這是一種傳統的說法,從傳統dom的操作方式來的,但是在react中,使用這種方法描述組件間的通信是不合適的。在我看來,用事件通知模型來描述可能更合適。
0x001 父組件向子組件發起通信父組件向子組件發起通信很簡單,直接使用props
import React from "react" import ReactDom from "react-dom" class Sub extends React.Component { constructor() { super() this.state = { num: 0 } } componentWillReceiveProps(nextProps) { this.setState({ num: nextProps.num }) } render() { return} } class App extends React.Component { constructor() { super() this.state = { num: 0 } setInterval(() => { this.setState({ num: ++this.state.num }) }, 1000) } render() { return } } ReactDom.render(props.num:{this.props.num}
state.num:{this.state.num}
, document.getElementById("app") )
查看瀏覽器:
說明:App組件每秒更新一次num,同時將num通過props傳遞給子組件Sub,Sub通過props訪問父級傳遞下來的num,并渲染到界面上,同時也將該參數保存到自己的state中,也渲染到界面上。可以看到,父級更新了num,子組件也同步更新了,也就完成了父組件向子組件發起通信的目的。
0x002 子組件向父組件發起通信子組件向父組件發起通信則是通過事件觸發,我們可以想想平時的html:
我們給button綁定了click事件,所以當我們點擊按鈕的時間,該事件就會被觸發,然后執行我們的函數ourFunc并傳遞參數"you click me",這就是事件通知?,F在我們假設button是我們實現的自定義組件,那么onclick就是我們傳遞的props。眾所周知,js中,函數也是變量,所以在react中,props也可以傳遞函數:
import React from "react" import ReactDom from "react-dom" class MyButton extends React.Component { constructor() { super() this.state = { num: 0 } } handleOnClick() { let num = ++this.state.num this.setState({ num: num }) this.props.onClick(num) } render() { return } } class App extends React.Component { constructor() { super() this.state = { num: 0 } } render() { return} handleOnClick(num) { this.setState({ num: num }) } } ReactDom.render(點擊了 {this.state.num} 次
this.handleOnClick(text)}/> , document.getElementById("app") )
查看瀏覽器:
說明:我們聲明了一個MyButton組件,并傳遞了兩個屬性,一個是text,一個是onClick,注意,這里的onClick只是一個名字叫做onClick的屬性,而不是點擊事件,只是我們借用了這個名字而已,真正的點擊事件必須綁定在dom上。所以這里叫什么名字都無所謂,不過為了好看,還是叫著名字比較好。
在MyButton中,我們真正的綁定了onClick事件,并在該事件觸發的時候,調用傳遞過來的props.onClick,并吧點擊的次數作為參數,這樣,App的handleOnClick就會被促發,同時接收到num參數,用于顯示用戶的點擊次數。
從表面上看,我們就好像在MyButton上綁定了事件一般,和web中的十分類似,但是這種機制更加的靈活,比如我們不一定要叫onClick,我們可以將之和業務綁定,叫做onUserAdd,這樣,似乎就實現了自定義事件,并且具有一定的業務特點,非常的靈活。
兄弟組件通信其實很簡單,借助公共的父組件作為中間橋梁,然后通過上面說的props和事件機制,就完成了兄弟組件的通信,
稍微修改一下0x002的栗子就可以搞定了
class MyView extends React.Component { render() { return點擊了 {this.props.num} 次
} } class MyButton extends React.Component { constructor() { super() this.state = { num: 0 } } handleOnClick() { let num = ++this.state.num this.setState({ num: num }) this.props.onClick(num) } render() { return } } class App extends React.Component { constructor() { super() this.state = { num: 0 } } render() { return} handleOnClick(num) { this.setState({ num: num }) } } ReactDom.render(this.handleOnClick(text)}/> , document.getElementById("app") )
查看瀏覽器:
說明:MyButton和MyView是掛載在App的子組件,他們是同級的兄弟組件,而他們之間的通信可以借助App作為中轉,將數據從一個MyButton傳遞到MyView。具體過程:
MyButton點擊事件觸發后觸發父組件傳遞進來的onClick
App監聽MyButton的onClick事件并將該事件的num保存到自己的state中
而state.num又傳遞到了MyView中
所以當我們點擊按鈕的時候,點擊次數就增加了。
0x004 遠程組件通信從上克制,組件間的通信可以通過props傳遞普通變量和函數來實現,但是如果事件嵌套的層級太深,這套模型就顯得麻煩,必須要不斷的傳遞props,不但冗余而且不好維護。
當然我們也可以通過適當的組件設計來避免過深的組件嵌套通信。
那如果無法避免呢?
那就需要用其他方式來實現了,比如,使用訂閱-發布模型可以實現無視距離和組件的通信,甚至無視框架和位置,但是很容易引起混亂,適用于全局通知。
以下是簡單實現:
實現通用的訂閱-發布模型框架
let eventMap = {} class MyEvent { static pub(name, data) { if (!eventMap.hasOwnProperty(name)) return let callbacks = eventMap[name] if (callbacks.length === 0) return callbacks.forEach((callback) => { callback(data) }) } static sub(name, callback) { let callbacks = [] if (eventMap.hasOwnProperty(name)) { callbacks = eventMap[name] } callbacks.push(callback) eventMap[name] = callbacks } } export default MyEvent
該框架只有兩個方法,和一個事件隊列,pub用來發布一個事件,sub用來訂閱一個事件,調用pub發布一個事件以后,sub了該事件的方法就會被執行
MyEvent.sub("EventA",(data)=>{console.log(data)}) MyEvent.pub("EventA",{num:1}) // 查看控制臺 {num:1}
編寫組件
const EVENT_BUTTON_CLICK = "EVENT_BUTTON_CLICK" class MyView extends React.Component { constructor() { super() this.state = { num: 0 } MyEvent.sub(EVENT_BUTTON_CLICK, (num) => { this.setState({ num: num.num }) }) } render() { return點擊了 {this.state.num} 次
} } class MyButton extends React.Component { constructor() { super() this.state = { num: 0 } } handleOnClick() { let num = ++this.state.num this.setState({ num: num }) MyEvent.pub(EVENT_BUTTON_CLICK, {num: num}) } render() { return } } class App extends React.Component { constructor() { super() } render() { return} } ReactDom.render(, document.getElementById("app") )
可以看到,我們使用的是發布-訂閱模型,并沒有通過父組件來做兄弟組件的傳遞中介,沒有太多的props嵌套。所以這就解決了遠程組件通信、深度組件嵌套的問題。當然也帶來了另一個問題,那就是事件維護。如果事件太多,將會導致無法維護和流程混亂......不可亂用,可用于系統的中心事件控制,也就是單一的事件源輸出。
組件間通信可以選擇像redux這樣的庫來處理。
0x005 資源react
源碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97250.html
摘要:概述也是一個新的數據結構,在中其實也經常用到,比如下面的栗子,我們經常這么使用一個對象,與其說他是對象,其實他更像一個,但是比起真正的,這個還是有點弱了,初始化初始化一個有一個可選的參數,該參數必須是一個可迭代對象,可迭代對象包括和用戶定 0x000 概述 Map也是一個新的數據結構,在js中其實也經常用到,比如下面的栗子,我們經常這么使用一個對象,與其說他是對象,其實他更像一個Map...
摘要:入門學習筆記整理一搭建環境入門學習筆記整理二簡介與語法入門學習筆記整理三組件入門學習筆記整理四事件入門學習筆記整理五入門學習筆記整理六組件通信入門學習筆記整理七生命周期入門學習筆記整理八入門學習筆記整理九路由React 入門學習筆記整理(一)——搭建環境 React 入門學習筆記整理(二)—— JSX簡介與語法 React 入門學習筆記整理(三)—— 組件 React 入門學習筆記整理(...
摘要:年終總結結果到這個時間才寫,其實也是無奈。這一年最重要的事情就是順利從一只學生狗轉職為一只社畜。四月份畢業之后以前端工程師的職位入職天貓,到現在也差不多工作一年了。 年終總結結果到這個時間才寫,其實也是無奈。本來計劃過年寫的,沒想到Steam竟然開了個農歷春節特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身 以下全都是個人看法,如果有不認同的地方,請大吼一聲...
摘要:年終總結結果到這個時間才寫,其實也是無奈。這一年最重要的事情就是順利從一只學生狗轉職為一只社畜。四月份畢業之后以前端工程師的職位入職天貓,到現在也差不多工作一年了。 年終總結結果到這個時間才寫,其實也是無奈。本來計劃過年寫的,沒想到Steam竟然開了個農歷春節特惠,然后就被各種游戲打了,辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身 以下全都是個人看法,如果有不認同的地方,請大吼一聲...
閱讀 1354·2021-09-10 10:51
閱讀 2829·2019-08-30 15:54
閱讀 3367·2019-08-29 17:11
閱讀 925·2019-08-29 16:44
閱讀 1390·2019-08-29 13:47
閱讀 1085·2019-08-29 13:47
閱讀 1485·2019-08-29 12:23
閱讀 1037·2019-08-28 18:18