一、父传子
父组件:
class App extends Component {
render() {
return (
<div>
{/* 类组件 */}
<Child name="李四" age={26} hobbies={['睡觉']} />
{/* 类组件默认值 */}
<Child />
{/* 函数组件 */}
<Child2 />
</div>
)
}
}
类子组件:
class Child extends Component {
render() {
const { name, age, hobbies } = this.props;
return (
<div>
<h3>{`姓名:${name},年龄:${age}`}</h3>
<h3>爱好:</h3>
<ul>
{
hobbies.map(item => {
return <li key={item}>{item}</li>
})
}
</ul>
</div>
)
}
}
函数子组件:
function Child2(props) {
const { name, age, hobbies } = props;
return (
<div>
<h3>{`姓名:${name},年龄:${age}`}</h3>
<h3>爱好:</h3>
<ul>
{
hobbies.map(item => {
return <li key={item}>{item}</li>
})
}
</ul>
</div>
)
}
类子组件中设置默认值及类型检查:
class Child extends Component {
// 类型检查
static propTypes = {
// isRequired 必传
name: PropTypes.string.isRequired,
age: PropTypes.number,
hobbies: PropTypes.array
}
// 设置默认值
static defaultProps = {
name: "小明",
age: 18,
hobbies: ['吃饭', '睡觉', '打豆豆']
}
render() {
const { name, age, hobbies } = this.props;
return (
<div>
<h3>{`姓名:${name},年龄:${age}`}</h3>
<h3>爱好:</h3>
<ul>
{
hobbies.map(item => {
return <li key={item}>{item}</li>
})
}
</ul>
</div>
)
}
}
函数组件和类组件通用设置默认值及类型检查:
// 类型检查
Child2.propTypes = {
// isRequired 必传
name: PropTypes.string.isRequired,
age: PropTypes.number,
hobbies: PropTypes.array
}
// 设置默认值
Child2.defaultProps = {
name: "小明",
age: 18,
hobbies: ['吃饭', '睡觉', '打豆豆']
}
二、子传父
父组件:
class App extends Component {
constructor() {
super();
this.state = {
data: []
}
}
render() {
return (
<div>
<Child getData={this.handleGetData} />
<h2>列表:</h2>
<ul>
{
this.state.data.map(item => {
return <li key={item}>{item}</li>
})
}
</ul>
</div>
)
}
// 定义箭头函数接收子组件传过来的值
handleGetData = (data) => {
this.setState({
data
})
}
}
子组件:
class Child extends Component {
constructor() {
super();
this.state = {
// 子组件初始值
data: ['a', 'b', 'c']
}
}
render() {
const { getData } = this.props;
return (
// 将子组件的值传递到父组件
<button onClick={e => getData(this.state.data)}>获取数据</button>
)
}
}
三、跨组件通信(context)
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
父组件:
// 创建 Context 并设置默认值
const listContext = React.createContext([111, 222, 333])
// 父组件
class App extends Component {
constructor() {
super();
this.state = {
list: ['aaa', 'bbb', 'ccc']
}
}
render() {
return (
<div>
<div>我是父组件</div>
{/* 调用 Provider 组件发送数据 */}
<listContext.Provider value={this.state}>
<Child />
</listContext.Provider>
</div>
)
}
}
子组件:
class Child extends Component {
render() {
return (
<div>
<div>我是子组件</div>
<GrandSon />
</div>
)
}
}
孙子组件(类):
class GrandSon extends Component {
// 接收 Context
static contextType = listContext;
constructor() {
super();
this.state = {};
}
render() {
return (
<div>
<div>我是孙子组件</div>
<ul>
{
this.context.list.map(item => {
return <li key={item}>{item}</li>
})
}
</ul>
</div>
)
}
}
- 通过类组件里定义
static contextType
接收父组件传递过来的 Context 值。**
// 接收父组件传递过来的 Context 值
static contextType = listContext;
- 通过组件名调用 ContextType 接收父组件传递过来的 Context 值。
// 通过类名接收父组件传递过来的 Context 值
GrandSon.contextType = listContext;
孙子组件(函数):
function GrandSon() {
return (
<div>
<div>我是孙子组件</div>
<ul>
{/* 通过 Consumer 组件接收数据 */}
<listContext.Consumer>
{
value => {
return value.list.map(item => {
return <li key={item}>{item}</li>
})
}
}
</listContext.Consumer>
</ul>
</div>
)
}
四、兄弟组件通信(events)
import React, { PureComponent } from 'react';
import { EventEmitter } from 'events';
// 定义事件总线
const eventsBus = new EventEmitter();
// 子组件1
class Child1 extends PureComponent {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
// 监听事件总线获取的值
componentDidMount() {
eventsBus.addListener('sayHello', this.handleSayHelloListener.bind(this))
}
handleSayHelloListener(message) {
this.setState({
message
})
}
// 销毁监听事件
componentWillUnmount() {
eventsBus.removeListener('sayHello', this.handleSayHelloListener);
}
render() {
return (
<div>
子组件1
<h2>子组件2的消息:</h2>
{this.state.message}
</div>
)
}
}
// 子组件2
class Child2 extends PureComponent {
render() {
return (
<div>
子组件2
<button onClick={() => this.sendMsg()}>发送消息</button>
</div>
)
}
// 从子组件 2 发送消息至子组件 1
sendMsg() {
eventsBus.emit('sayHello', '你好,我是子组件2', 666)
}
}
class App extends PureComponent {
render() {
return (
<div>
<Child1 />
<Child2 />
</div>
);
}
}
export default App;