React框架 - 组件之间通讯
React 父子组件、兄弟组件、叔侄应该如何进行通讯,这里描述一下两种方法。
props function
缺点:
- 操作繁琐,组件关系越复杂代码量越多。
- 耦合性太强。
消息 订阅与发布
优点:
- 只需在指定的位置进行订阅消息、发布消息即可。
- 极大程度上降低耦合性。
1. 通过props function进行通讯
原理:
找到父子、兄弟、叔侄组件的共同组件,绑定props function,进行通讯。
1.1. 类式组件用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import React, { Component } from "react"; import List from "./compoments/List"; import Search from "./compoments/Search";
export default class App extends Component { state = { datas: [] }; dataChange = (data) => { let { datas } = this.state; datas.push(data); this.setState({ datas: datas }); }; render() { return ( <div> <Search dataChange={this.dataChange} /> <List datas={this.state.datas} /> </div> ); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React, { Component } from "react";
export default class List extends Component { render() { return ( <div> {this.props.datas.map((data) => { return <div key={data.id}>{data.name}</div>; })} </div> ); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import React, { Component } from "react";
export default class Search extends Component { dataChange = () => { this.props.dataChange({ id: Date.now(), name: "加了加了" }); }; render() { return ( <div> <button onClick={this.dataChange}>点击添加一条数据</button> </div> ); } }
|
1.2. 函数式组件用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import React, { Component } from "react"; import List from "./compoments/List"; import Search from "./compoments/Search";
export default class App extends Component { state = { datas: [] }; dataChange = (data) => { let { datas } = this.state; datas.push(data); this.setState({ datas: datas }); }; render() { return ( <div> <Search dataChange={this.dataChange} /> <List datas={this.state.datas} /> </div> ); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| import React from "react";
export default function List(props) { return ( <div> {props.datas.map((data) => { return <div key={data.id}>{data.name}</div>; })} </div> ); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react";
export default function Search(props) { let dataChange = () => { props.dataChange({ id: Date.now(), name: "加了加了" }); }; return ( <div> <button onClick={dataChange}>点击添加一条数据</button> </div> ); }
|
通过function dataChange进行通信。
操作繁琐,本应跟App.jsx无关的操作,现在代码放到了App.jsx中。
2. 消息 订阅与发布
接着使用上面的例子。通过比较可以直接看出优缺点。
不能直接使用,需要安装额外的组件库。这里使用的是PubSubJS,详细内容请查看PubSubJS笔记。
2.1. 类式组件用法
1 2 3 4 5 6 7 8 9 10 11 12 13
| import React, { Component } from 'react'; import List from './compoments/List'; import Search from './compoments/Search';
export default class App extends Component { render() { return <div> <Search /> <List /> </div> } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import React, { Component } from 'react'; import PubSub from 'pubsub-js';
export default class List extends Component { state={datas:[]} componentDidMount(){ this.dataChangeToken = PubSub.subscribe("dataChange", (msg, data) => { let { datas } = this.state; datas.push(data); this.setState({ datas: datas }); }); }
componentWillUnmount(){ PubSub.unsubscribe(this.dataChangeToken); } render() { return <div> { this.state.datas.map(data=>{ return <div key={data.id}>{data.name}</div> }) } </div> } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React, { Component } from 'react'; import PubSub from 'pubsub-js';
export default class Search extends Component { dataChange=()=>{ PubSub.publish("dataChange", { id: Date.now(), name: "加了加了" }); } render() { return <div> <button onClick={this.dataChange}>我点</button> </div> } }
|
- 兄弟组件之间通讯直接通过发布、订阅消息,使得父组件App.jsx只需要管理组件摆放位置即可。
- 这里用到的消息发布订阅的组件包是PubSubJS。
- token的管理不能像本文中直接使用字符串,需要设定一个TOKEN工厂来统一进行管理。
3. 集中式管理
redux
TODO: 有机会整理
4. conText
TODO: 有机会整理