面試官:React中組件之間通信的方式有哪些?
本文轉(zhuǎn)載自微信公眾號(hào)「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請(qǐng)聯(lián)系JS每日一題公眾號(hào)。
一、是什么
我們將組件間通信可以拆分為兩個(gè)詞:
- 組件
- 通信
回顧Vue系列的文章,組件是vue中最強(qiáng)大的功能之一,同樣組件化是React的核心思想
相比vue,React的組件更加靈活和多樣,按照不同的方式可以分成很多類型的組件
而通信指的是發(fā)送者通過(guò)某種媒體以某種格式來(lái)傳遞信息到收信者以達(dá)到某個(gè)目的,廣義上,任何信息的交通都是通信
組件間通信即指組件通過(guò)某種方式來(lái)傳遞信息以達(dá)到某個(gè)目的
二、如何通信
組件傳遞的方式有很多種,根據(jù)傳送者和接收者可以分為如下:
- 父組件向子組件傳遞
- 子組件向父組件傳遞
- 兄弟組件之間的通信
- 父組件向后代組件傳遞
- 非關(guān)系組件傳遞
父組件向子組件傳遞
由于React的數(shù)據(jù)流動(dòng)為單向的,父組件向子組件傳遞是最常見(jiàn)的方式
父組件在調(diào)用子組件的時(shí)候,只需要在子組件標(biāo)簽內(nèi)傳遞參數(shù),子組件通過(guò)props屬性就能接收父組件傳遞過(guò)來(lái)的參數(shù)
- function EmailInput(props) {
- return (
- <label>
- Email: <input value={props.email} />
- </label>
- );
- }
- const element = <EmailInput email="123124132@163.com" />;
子組件向父組件傳遞
子組件向父組件通信的基本思路是,父組件向子組件傳一個(gè)函數(shù),然后通過(guò)這個(gè)函數(shù)的回調(diào),拿到子組件傳過(guò)來(lái)的值
父組件對(duì)應(yīng)代碼如下:
- class Parents extends Component {
- constructor() {
- super();
- this.state = {
- price: 0
- };
- }
- getItemPrice(e) {
- this.setState({
- price: e
- });
- }
- render() {
- return (
- <div>
- <div>price: {this.state.price}</div>
- {/* 向子組件中傳入一個(gè)函數(shù) */}
- <Child getPrice={this.getItemPrice.bind(this)} />
- </div>
- );
- }
- }
子組件對(duì)應(yīng)代碼如下:
- class Child extends Component {
- clickGoods(e) {
- // 在此函數(shù)中傳入值
- this.props.getPrice(e);
- }
- render() {
- return (
- <div>
- <button onClick={this.clickGoods.bind(this, 100)}>goods1</button>
- <button onClick={this.clickGoods.bind(this, 1000)}>goods2</button>
- </div>
- );
- }
- }
兄弟組件之間的通信
如果是兄弟組件之間的傳遞,則父組件作為中間層來(lái)實(shí)現(xiàn)數(shù)據(jù)的互通,通過(guò)使用父組件傳遞
- class Parent extends React.Component {
- constructor(props) {
- super(props)
- this.state = {count: 0}
- }
- setCount = () => {
- this.setState({count: this.state.count + 1})
- }
- render() {
- return (
- <div>
- <SiblingA
- count={this.state.count}
- />
- <SiblingB
- onClick={this.setCount}
- />
- </div>
- );
- }
- }
父組件向后代組件傳遞
父組件向后代組件傳遞數(shù)據(jù)是一件最普通的事情,就像全局?jǐn)?shù)據(jù)一樣
使用context提供了組件之間通訊的一種方式,可以共享數(shù)據(jù),其他數(shù)據(jù)都能讀取對(duì)應(yīng)的數(shù)據(jù)
通過(guò)使用React.createContext創(chuàng)建一個(gè)context
- const PriceContext = React.createContext('price')
context創(chuàng)建成功后,其下存在Provider組件用于創(chuàng)建數(shù)據(jù)源,Consumer組件用于接收數(shù)據(jù),使用實(shí)例如下:
Provider組件通過(guò)value屬性用于給后代組件傳遞數(shù)據(jù):
- <PriceContext.Provider value={100}>
- </PriceContext.Provider>
如果想要獲取Provider傳遞的數(shù)據(jù),可以通過(guò)Consumer組件或者或者使用contextType屬性接收,對(duì)應(yīng)分別如下:
- class MyClass extends React.Component {
- static contextType = PriceContext;
- render() {
- let price = this.context;
- /* 基于這個(gè)值進(jìn)行渲染工作 */
- }
- }
Consumer組件:
- <PriceContext.Consumer>
- { /*這里是一個(gè)函數(shù)*/ }
- {
- price => <div>price:{price}</div>
- }
- </PriceContext.Consumer>
非關(guān)系組件傳遞
如果組件之間關(guān)系類型比較復(fù)雜的情況,建議將數(shù)據(jù)進(jìn)行一個(gè)全局資源管理,從而實(shí)現(xiàn)通信,例如redux。關(guān)于redux的使用后續(xù)再詳細(xì)介紹
三、總結(jié)
由于React是單向數(shù)據(jù)流,主要思想是組件不會(huì)改變接收的數(shù)據(jù),只會(huì)監(jiān)聽(tīng)數(shù)據(jù)的變化,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)它們會(huì)使用接收到的新值,而不是去修改已有的值
因此,可以看到通信過(guò)程中,數(shù)據(jù)的存儲(chǔ)位置都是存放在上級(jí)位置中
參考文獻(xiàn)
https://react.docschina.org/docs/context.html