Углубленная серия React, подробное объяснение ключевых концепций, функций и шаблонов в React, призвана помочь вам углубить ваше понимание React и более гибко использовать React в ваших проектах.
Это последняя часть подробной серии статей о React. В ней будут представлены шаблоны, которые часто используются при разработке приложений React. Эти шаблоны не имеют официальных названий, поэтому названия некоторых шаблонов могут быть неточными. Обратите внимание на содержание узоров.
1. Контролируемые компоненты
Поток данных компонентов React управляется состоянием и свойствами, но для таких элементов формы, как ввод, текстовое поле, выбор и т. д., поскольку он может напрямую получать пользовательский ввод в интерфейсе, он разрушает естественный поток данных в React. Чтобы решить эту проблему, React вводит контролируемые компоненты.Контролируемые компоненты относятся к значениям, отображаемым элементами формы, такими как ввод, которые по-прежнему получаются через состояние компонента, а не напрямую отображают введенную пользователем информацию в интерфейсе. .
Реализация контролируемого компонента: путем отслеживания изменения значения элемента формы, изменения состояния компонента и отображения конечного значения компонента в соответствии с состоянием. Простой пример выглядит следующим образом:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Концепция, соответствующая управляемому компоненту, является неуправляемым компонентом.Неуправляемый компонент получает значение элемента формы через ref, который играет уникальную роль в некоторых сценариях (например, установка фокуса элемента формы).
2. Компоненты контейнера
Компоненты-контейнеры и компоненты представления представляют собой набор соответствующих концепций, ориентированных на разделение логики компонентов и представления компонентов. Логика обрабатывается компонентом-контейнером, а компонент представления фокусируется на представлении уровня представления. существуетReact In-Depth Series 2: Классификация компонентовКомпоненты-контейнеры и компоненты отображения подробно описаны в разделе , поэтому я не буду повторять их здесь.
3. Компоненты высокого порядка
Компонент высшего порядка — это особый вид функции, которая принимает компонент в качестве входных данных и выводит новый компонент. Основная функция компонентов высшего порядка — инкапсулировать общую логику компонентов и реализовать повторное использование логики. существуетПодробно о React, серия 6: Компоненты высшего порядкаКомпоненты высокого уровня были подробно описаны в разделе , и здесь они повторяться не будут.
4. Дети проходят
Во-первых, название этого шаблона может быть неподходящим. В этом режиме развязка между компонентами достигается с помощью дочернего свойства компонентов React. Обычно используется во фреймворке, где компонент отвечает за пользовательский интерфейс, а компоненты внутри фреймворка можно гибко заменять.
Пример:
// ModalDialog.js
export default function ModalDialog({ children }) {
return <div className="modal-dialog">{ children }</div>;
};
// App.js
render() {
<ModalDialog>
<SomeContentComp/>
</ModalDialog>
}
Компонент ModalDialog представляет собой блок пользовательского интерфейса, и компоненты в блоке можно гибко заменять.
5. Render Props
Реквизиты рендеринга инкапсулируют логику рендеринга части компонента в функцию, используют реквизиты компонента для получения этой функции, а затем вызывают эту функцию внутри компонента для выполнения инкапсулированной логики рендеринга.
См. официальный пример:
class Cat extends React.Component {
render() {
const mouse = this.props.mouse;
return (
<img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
);
}
}
class Mouse extends React.Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.state = { x: 0, y: 0 };
}
handleMouseMove(event) {
this.setState({
x: event.clientX,
y: event.clientY
});
}
render() {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
{/*
* Mouse组件并不知道应该如何渲染这部分内容,
* 这部分渲染逻辑是通过props的render属性传递给Mouse组件
*/}
{this.props.render(this.state)}
</div>
);
}
}
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>Move the mouse around!</h1>
<Mouse render={mouse => (
<Cat mouse={mouse} />
)}/>
</div>
);
}
}
Мышь слушает движение мыши и сохраняет положение мыши в состоянии. Однако компонент Mouse не знает окончательного содержимого, которое необходимо отобразить, и ему необходимо вызвать метод this.props.render для выполнения логики отрисовки. В этом примере компонент «Кот» будет отображаться в том месте, куда движется мышь, но другие эффекты могут использоваться для отслеживания движения мыши, просто измените метод рендеринга. Видно, что компонент «Мышь» обращает внимание только на перемещение положения мыши, а интерфейсный эффект, следующий за движением мыши, определяется компонентом, который использует «Мышь». Это идея, основанная на аспектном программировании (студенты, разбирающиеся в бэкенд-разработке, должны быть с ней знакомы).
Используя этот шаблон, обычной практикой является назначение функции, которая инкапсулирует логику рендеринга, свойству компонента с именем render (как в этом примере), но это не обязательно, вы также можете использовать другие имена свойств.
Разновидностью этого шаблона является его передача напрямую с использованием свойства children, которое поставляется с компонентом React. Приведенный выше пример переписывается как:
class Mouse extends React.Component {
// 省略
render() {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
{/*
* Mouse组件并不知道应该如何渲染这部分内容,
* 这部分渲染逻辑是通过props的children属性传递给Mouse组件
*/}
{this.props.children(this.state)}
</div>
);
}
}
Mouse.propTypes = {
children: PropTypes.func.isRequired
};
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>Move the mouse around!</h1>
<Mouse>
{mouse => (
<Cat mouse={mouse} />
)}
</Mouse>
</div>
);
}
}
Обратите внимание на то, как распределены дети.
И React Router, и библиотеки React-Motion используют шаблон Render Props. ** Во многих сценариях функции, реализованные Render Props, также могут быть реализованы с помощью компонентов более высокого порядка. **Этот пример также может быть реализован с компонентами более высокого порядка, подумайте сами.
6. Компонент провайдера
Этот режим использует контекст React для сохранения данных, которые компонент должен использовать в контексте, и предоставляет компонент более высокого порядка для получения данных из контекста.
один пример:
Сначала создайте MyProvider и сохраните общие данные в его контексте. MyProvider обычно используется в качестве компонента верхнего уровня, чтобы другие компоненты могли получать данные в контексте:
import React from "react";
import PropTypes from "prop-types";
const contextTypes = {
sharedData: PropTypes.shape({
a: PropTypes.bool,
b: PropTypes.string,
c: PropTypes.object
})
};
export class MyProvider extends React.Component {
static childContextTypes = contextTypes;
getChildContext() {
// 假定context中的数据从props中获取
return { sharedData: this.props.sharedData };
}
render() {
return this.props.children;
}
}
Затем создайте компонент более высокого порядка connectData, чтобы получить необходимые данные из контекста:
export const connectData = WrappedComponent =>
class extends React.Component {
static contextTypes = contextTypes;
render() {
const { props, context } = this;
return <WrappedComponent {...props} {...context.sharedData} />;
}
};
И, наконец, в приложении используйте:
const SomeComponentWithData = connectData(SomeComponent)
const sharedData = {
a: true,
b: "react",
c: {}
};
class App extends Component {
render() {
return (
<MyProvider sharedData={sharedData}>
<SomeComponentWithData />
</MyProvider>
);
}
}
Шаблон компонента Provider очень практичен и используется в таких библиотеках, как react-redux и mobx-react.
Это конец серии статей, посвященных React, в надежде помочь вам глубже понять React и более эффективно применять React.
Моя новая книга «Дорога к продвинутому React» поступила в продажу, студенты, интересующиеся React, могут захотеть узнать о ней. адрес покупки:Данданг Цзиндон
Добро пожаловать, чтобы обратить внимание на мой публичный аккаунт: большой фронт кадров ветеранов