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