В последнее время Alibaba Cloud проводит мероприятия со скидкой всего 20%, вы можете посмотреть, если вам интересно:Promotion.aliyun.com/ваша ТМ есть/облака боятся жары…
Чтобы обеспечить удобочитаемость, в этой статье используется вольный перевод, а не дословный перевод.
Расширенные компоненты React
Функции высшего порядка принимают функции в качестве аргументов и возвращают функции, которые также являются функциями. Точно так же компоненты высшего порядка (сокращенно HOC) принимают компоненты React в качестве аргументов и возвращают новый компонент React. Компонент более высокого порядка по существу является функцией, а не компонентом. Функциональная форма компонентов более высокого порядка выглядит следующим образом:
Чтобы читать больше качественных статей, пожалуйстаПосетите блог GitHub, Сотни качественных статей ждут вас каждый год!
const EnhanceComponent = higherOrderComponent(WrappedComponent)
通过一个简单的例子解释高阶组件是如何复用的。现在有一个组件MyComponent,需要从LocalStorage中获取数据,然后渲染到界面。一般情况下,我们可以这样实现:
import React, { Component } from 'react'
class MyComponent extends Component {
componentWillMount() {
let data = localStorage.getItem('data');
this.setState({data});
}
render() {
return(
<div>{this.state.data}</div>
)
}
}
Код очень простой, но когда другим компонентам тоже нужно получить те же данные из LocalStorage и отобразить их, каждому компоненту нужно один раз переписать код в componentWillMount, что, очевидно, очень избыточно. Позвольте мне взглянуть на переписывание этой части кода с использованием компонентов более высокого порядка.
import React, { Component } from 'react'
function withPersistentData(WrappedComponent) {
return class extends Component {
componentWillMount() {
let data = localStorage.getItem('data');
this.setState({data});
}
render() {
// 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
return <WrappedComponent data={this.state.data} {...this.props}/>
}
}
}
class MyComponent extends Component{
render() {
return <div>{this.props.data}</div>
}
}
const MyComponentWithPersistentData = withPersistentData(MyComponent);
withPersistentData — компонент высокого порядка, который возвращает новый компонент, в новом компоненте componentWillMount единообразно обрабатывает логику получения данных из LocalStorage, а затем передает полученные данные в обернутый компонент WrappedComponent через пропсы, так что в WrappedComponent можно непосредственно используйте this.props.data для отображения данных.Если другим компонентам также нужна эта логика, продолжайте использовать компонент более высокого порядка withPersistentData для переноса этих компонентов.
2. Сценарии использования
Сценарии использования компонентов более высокого порядка в основном включают следующие четыре:
- Управление реквизитом
- Доступ к экземпляру компонента через ref
- улучшение состояния компонента
- Оберните компоненты другими элементами
1. Работа с реквизитом
Прежде чем упакованный компонент получит реквизиты, компонент более высокого порядка может перехватить реквизиты, добавить, удалить или изменить реквизиты, а затем передать обработанные реквизиты упакованному компоненту, как в первом примере.
2. Доступ к экземпляру компонента через ref
Компонент более высокого порядка ref получает ссылку на экземпляр упакованного компонента, а затем компонент более высокого порядка имеет возможность напрямую манипулировать свойствами или методами упакованного компонента.
import React, { Component } from 'react'
function withRef(wrappedComponent) {
return class extends Component{
constructor(props) {
super(props);
this.someMethod = this.someMethod.bind(this);
}
someMethod() {
this.wrappedInstance.comeMethodInWrappedComponent();
}
render() {
// 为被包装组件添加 ref 属性,从而获取组件实例并赋值给 this.wrappedInstance
return <wrappedComponent ref={(instance) => { this.wrappedInstance = instance }} {...this.props}/>
}
}
}
При рендерингеwrappedComponent выполняется функция обратного вызова ref, компонент более высокого порядка сохраняет ссылку экземпляраwrappedComponent через this.wrappedInstance и вызывает метод в wrapComponent через this.wrappedInstance в someMethod. Это использование редко используется в реальных проектах, но когда логика повторного использования, инкапсулированная компонентами более высокого порядка, должна поддерживаться методами или свойствами упакованных компонентов, такое использование полезно.
3. Улучшение статуса компонента
Компонент более высокого порядка может реализовать отсутствие состояния упакованного компонента путем переноса состояния упакованного компонента и соответствующего метода обработки состояния в сам компонент более высокого порядка. Типичный сценарий заключается в использовании компонентов более высокого порядка для равномерного переноса состояния, при котором исходно контролируемые компоненты должны поддерживаться сами по себе, в компоненты более высокого порядка.
import React, { Component } from 'react'
function withRef(wrappedComponent) {
return class extends Component{
constructor(props) {
super(props);
this.state = {
value: ''
}
this.handleValueChange = this.handleValueChange.bind(this);
}
handleValueChange(event) {
this.this.setState({
value: event.EventTarget.value
})
}
render() {
// newProps保存受控组件需要使用的属性和事件处理函数
const newProps = {
controlledProps: {
value: this.state.value,
onChange: this.handleValueChange
}
}
return <wrappedComponent {...this.props} {...newProps}/>
}
}
}
В этом примере продвигается состояние, используемое атрибутом значения контролируемого компонента, и функция обратного вызова, которая обрабатывает изменение значения, на компонент более высокого порядка.Когда мы снова используем контролируемый компонент, мы можем использовать его следующим образом:
import React, { Component } from 'react'
function withControlledState(wrappedComponent) {
return class extends Component{
constructor(props) {
super(props);
this.state = {
value: ''
}
this.handleValueChange = this.handleValueChange.bind(this);
}
handleValueChange(event) {
this.this.setState({
value: event.EventTarget.value
})
}
render() {
// newProps保存受控组件需要使用的属性和事件处理函数
const newProps = {
controlledProps: {
value: this.state.value,
onChange: this.handleValueChange
}
}
return <wrappedComponent {...this.props} {...newProps}/>
}
}
}
class SimpleControlledComponent extends React.Component {
render() {
// 此时的 SimpleControlledComponent 为无状态组件,状态由高阶组件维护
return <input name="simple" {...this.props.controlledProps}/>
}
}
const ComponentWithControlledState = withControlledState(SimpleControlledComponent);
3. Передача параметров
Параметр компонента более высокого порядка является не только компонентом, он также может принимать другие параметры. Например, первый — получить данные, ключ которых — данные из LocalStorage, а когда ключ для получения данных неясен, компонента более высокого порядка withPersistentData недостаточно. Мы можем заставить его принимать дополнительный параметр, чтобы решить, какие данные получать из LocalStorage:
import React, { Component } from 'react'
function withPersistentData(WrappedComponent, key) {
return class extends Component {
componentWillMount() {
let data = localStorage.getItem(key);
this.setState({ data });
}
render() {
// 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
return <WrappedComponent data={this.state.data} {...this.props} />
}
}
}
class MyComponent extends Component {
render() {
return <div>{this.props.data}</div>
}
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData(MyComponent, 'data');
// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData(MyComponent, 'name');
Новая версия withPersistentData отвечает потребностям получения разных значений ключей, но на практике мы редко используем этот метод для передачи параметров, а используем более гибкую и удобную форму функции:
HOC(...params)(WrappedComponent)
Возвращаемое значение HOC(...params) является компонентом более высокого порядка, и параметры, требуемые компонентом более высокого порядка, сначала передаются в функцию HOC. Перепишите withPersistentData в этой форме следующим образом (примечание: компоненты более высокого порядка в этой форме более точно определяются с помощью стрелочных функций):
import React, { Component } from 'react'
const withPersistentData = (key) => (WrappedComponent) => {
return class extends Component {
componentWillMount() {
let data = localStorage.getItem(key);
this.setState({ data });
}
render() {
// 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
return <WrappedComponent data={this.state.data} {...this.props} />
}
}
}
class MyComponent extends Component {
render() {
return <div>{this.props.data}</div>
}
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData('data')(MyComponent);
// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData('name')(MyComponent);
В-четвертых, метод наследования для достижения компонентов высокого порядка
Представленные выше методы реализации компонентов высокого порядка обрабатывают общую логику компонентами высокого порядка, а затем передают соответствующие свойства упакованным компонентам.Мы называем этот метод прокси свойств. Помимо прокси свойств, компоненты более высокого порядка также могут быть реализованы посредством наследования: повторное использование логики достигается за счет наследования упакованных компонентов. Компоненты более высокого порядка, реализованные путем наследования, часто используются для захвата рендеринга. Например, когда пользователь вошел в систему, разрешите визуализацию компонента, в противном случае визуализируйте пустой компонент. код показывает, как показано ниже:
function withAuth(WrappedComponent) {
return class extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render();
} else {
return null;
}
}
}
}
В соответствии с this.props.loggedIn компонента WrappedComponent определяется, вошел ли пользователь в систему. Если вход выполнен, метод рендеринга WrappedComponent вызывается через super.render() для нормальной визуализации компонента. В противном случае возвращается нуль. При объединении нескольких применений более высокого порядка легко потерять логику, потому что компонент подкласса забывает вызвать метод компонента суперкласса через super. Следовательно, при использовании компонентов более высокого порядка вы должны попытаться реализовать компоненты более высокого порядка через прокси.
Вышеизложенное в основном относится к книге «React Advanced Road».
общаться с
Статьи из серии галантерейных товаров резюмируются следующим образом: если вы чувствуете себя хорошо, нажмите «Звезда», добро пожаловать в группу, чтобы учиться друг у друга.
Я Сяо Чжи, автор официального аккаунта "Moving the World",Продолжайте знакомить энтузиастов с передовыми технологиями. Я буду часто делиться тем, что я узнал и увидел, На пути продвижения, давайте подбадривать друг друга!
Обратите внимание на публичный аккаунт и отвечайте в фоновом режимеБлагосостояние, вы можете увидеть преимущества, вы знаете.