впервые опубликовано вличный блог
Несколько ситуаций, требующих связи между компонентами
- Родительский компонент взаимодействует с дочерним компонентом
- Дочерний компонент взаимодействует с родительским компонентом
- Взаимодействие компонентов между уровнями
- Связь между компонентами без вложенных отношений
1. Родительский компонент взаимодействует с дочерним компонентом
Поток данных React является односторонним, и связь между родительскими компонентами и дочерними также является наиболее распространенной; родительские компоненты передают необходимую информацию дочерним компонентам через реквизиты. Ребенок.jsx
import React from 'react';
import PropTypes from 'prop-types';
export default function Child({ name }) {
return <h1>Hello, {name}</h1>;
}
Child.propTypes = {
name: PropTypes.string.isRequired,
};
Parent.jsx
import React, { Component } from 'react';
import Child from './Child';
class Parent extends Component {
render() {
return (
<div>
<Child name="Sara" />
</div>
);
}
}
export default Parent;
2. Дочерний компонент взаимодействует с родительским компонентом
- Используйте функции обратного вызова
- Используйте собственный механизм событий
Перезвоните
Реализуйте функцию, которая нажимает кнопку скрытия компонента в дочернем компоненте, чтобы скрыть себя
List3.jsx
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class List3 extends Component {
static propTypes = {
hideConponent: PropTypes.func.isRequired,
}
render() {
return (
<div>
哈哈,我是List3
<button onClick={this.props.hideConponent}>隐藏List3组件</button>
</div>
);
}
}
export default List3;
App.jsx
import React, { Component } from 'react';
import List3 from './components/List3';
export default class App extends Component {
constructor(...args) {
super(...args);
this.state = {
isShowList3: false,
};
}
showConponent = () => {
this.setState({
isShowList3: true,
});
}
hideConponent = () => {
this.setState({
isShowList3: false,
});
}
render() {
return (
<div>
<button onClick={this.showConponent}>显示Lists组件</button>
{
this.state.isShowList3 ?
<List3 hideConponent={this.hideConponent} />
:
null
}
</div>
);
}
}
Глядя на метод реализации, вы можете обнаружить, что он такой же, как метод реализации традиционной функции обратного вызова, более того, setState и функция обратного вызова обычно появляются в парах, потому что функция обратного вызова является традицией функции, которая преобразует внутреннее состояние;
3. Межуровневая коммуникация компонентов
- Послойные компоненты передают свойства
Например, для связи между компонентом A и компонентом B сначала найдите общий родительский компонент A и B, сначала свяжитесь с компонентом C, а компонент C взаимодействует с компонентом B через реквизиты.В это время компонент C играет роль промежуточного программного обеспечения.
- использовать контекст
Контекст — это глобальная переменная, подобная большому контейнеру, к которому можно получить доступ из любого места, мы можем поместить информацию для передачи в контекст, а затем ее можно будет свободно получить в других компонентах; Однако React официально не рекомендует использовать большое количество контекстов, хотя это и может уменьшить послойную передачу, но когда структура компонентов сложная, мы не знаем, откуда передается контекст, а контекст — это глобальная переменная , глобальная переменная - это именно то, что вызывает путаницу в приложении.
использовать контекст
Связь компонентов в следующем примере: ListItem — дочерний компонент List, List — дочерний компонент приложения.
ListItem.jsx
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class ListItem extends Component {
// 子组件声明自己要使用context
static contextTypes = {
color: PropTypes.string,
}
static propTypes = {
value: PropTypes.string,
}
render() {
const { value } = this.props;
return (
<li style={{ background: this.context.color }}>
<span>{value}</span>
</li>
);
}
}
export default ListItem;
List.jsx
import ListItem from './ListItem';
class List extends Component {
// 父组件声明自己支持context
static childContextTypes = {
color: PropTypes.string,
}
static propTypes = {
list: PropTypes.array,
}
// 提供一个函数,用来返回相应的context对象
getChildContext() {
return {
color: 'red',
};
}
render() {
const { list } = this.props;
return (
<div>
<ul>
{
list.map((entry, index) =>
<ListItem key={`list-${index}`} value={entry.text} />,
)
}
</ul>
</div>
);
}
}
export default List;
App.jsx
import React, { Component } from 'react';
import List from './components/List';
const list = [
{
text: '题目一',
},
{
text: '题目二',
},
];
export default class App extends Component {
render() {
return (
<div>
<List
list={list}
/>
</div>
);
}
}
4. Взаимодействие компонентов без вложенности
- Использовать собственный механизм событий
В событии componentDidMount, если компонент смонтирован, подпишитесь на событие, при размонтировании компонента отмените подписку на событие в событии componentWillUnmount; Возьмите в качестве примера обычный режим публикации/подписки и используйте браузерную версию модуля Node.js Events для реализации
Как использовать пользовательские события
Отношения компонентов в следующем примере: List1 и List2 не имеют отношения вложенности, а App является их родительским компонентом;
Реализуйте такую функцию: нажмите кнопку в List2, чтобы изменить отображение информации в List1. Во-первых, вам нужно установить пакет событий в проект:
npm install events --save
Создайте файл events.js в новом каталоге util в разделе src.
import { EventEmitter } from 'events';
export default new EventEmitter();
list1.jsx
import React, { Component } from 'react';
import emitter from '../util/events';
class List extends Component {
constructor(props) {
super(props);
this.state = {
message: 'List1',
};
}
componentDidMount() {
// 组件装载完成以后声明一个自定义事件
this.eventEmitter = emitter.addListener('changeMessage', (message) => {
this.setState({
message,
});
});
}
componentWillUnmount() {
emitter.removeListener(this.eventEmitter);
}
render() {
return (
<div>
{this.state.message}
</div>
);
}
}
export default List;
List2.jsx
import React, { Component } from 'react';
import emitter from '../util/events';
class List2 extends Component {
handleClick = (message) => {
emitter.emit('changeMessage', message);
};
render() {
return (
<div>
<button onClick={this.handleClick.bind(this, 'List2')}>点击我改变List1组件中显示信息</button>
</div>
);
}
}
APP.jsx
import React, { Component } from 'react';
import List1 from './components/List1';
import List2 from './components/List2';
export default class App extends Component {
render() {
return (
<div>
<List1 />
<List2 />
</div>
);
}
}
Пользовательские события — это типичная модель публикации-подписки, которая реализует связь между компонентами путем добавления слушателей к объектам событий и запуска событий.
Суммировать
- Родительский компонент общается с дочерним компонентом: реквизит
- Дочерний компонент взаимодействует с родительским компонентом: функция обратного вызова/пользовательское событие
- Взаимодействие компонентов между уровнями: компоненты уровня за уровнем передают реквизиты/контекст.
- Связь между компонентами без вложенных отношений: пользовательские события
При проведении компонентной коммуникации в основном зависит от конкретных потребностей бизнеса и выбирает наиболее подходящую; Когда бизнес-логика в определенной степени сложна, можно рассмотреть возможность введенияMobx,Reduxинструменты управления состоянием