Улучшенный дизайн компонентов React

React.js

Исходная ссылка: React Component Patterns

гитхаб-адресприветственная звезда

предисловие

Готовясь к техническому докладу на конференции, я хотел воспользоваться моментом, чтобы поделиться некоторыми своими мыслями о разработке шаблонов компонентов React. Компоненты лежат в основе React, и их понимание важно для разработки хорошей архитектуры проекта.

Схемы в тексте взяты из очень хорошей беседы (изMichael Chan) в собственности. Очень рекомендую посмотреть его видео

что такое компонент

Согласно официальному сайту Reactпредставлять, компоненты позволяют разделить пользовательский интерфейс на независимые повторно используемые части, вам нужно только продумать конструкцию каждой части отдельно.

когда вы впервые запускаетеnpm install react, вы можете получить исходный код React локально (путь./node_modules/react/umd/react.development.js), который можно рассматривать как большой компонент, предоставляющий ряд интерфейсов. Компоненты React похожи на функции JavaScript, компоненты принимают входные данные, называемые «реквизитами», и возвращают элементы React, которые описывают (декларируют) пользовательский интерфейс. Вы просто сообщаете React, как выглядит ваш пользовательский интерфейс, и React сделает за вас все остальное (синхронизируя DOM и данные) и отобразит интерфейс. Вот почему React называют декларативной библиотекой.

Декларативный означает, что если вы решите взять такси, когда собираетесь куда-то, вам нужно только сообщить водителю пункт назначения, и водитель сам довезет вас до места назначения. Императив противоположен и требует, чтобы вы сами доехали до места назначения.

API компонента

Итак, какие API вы получаете, загружая React? Их 5:

  • render
  • state
  • props
  • context
  • lifecycle events

Хотя компоненты предоставляют полный и простой в использовании API, вполне естественно, что некоторые компоненты используют часть API, а другие компоненты используют тот же API, что и раньше. Как правило, компоненты делятся на компоненты с состоянием и компоненты без состояния. Компоненты с состоянием часто используютсяrender, stateИ (события жизненного цикла) крючки жизненного цикла, компоненты без сохранения состояния обычно используютrender, props以及context.

Вот несколько шаблонов проектирования для компонентов React. Хороший шаблон проектирования — это передовая практика, которая четко разделяет уровень данных или логики и уровень пользовательского интерфейса (представления). Как правило, более крупный компонент можно разделить в соответствии с функциональными обязанностями, чтобы можно было реализовать более многоразовые и высокосвязные компоненты, которые можно легко использовать для создания сложных пользовательских интерфейсов. Это особенно важно при создании масштабируемых приложений.

Шаблоны проектирования компонентов

Общие шаблоны проектирования:

  • Компонент контейнера
  • Презентационная составляющая
  • Компоненты высшего порядка
  • Рендеринг обратных вызовов

Компонент контейнера

Компоненты-контейнеры взаимодействуют (общаются) с внешними данными, а затем визуализируют соответствующие дочерние компоненты — Джейсон Бонта.

Синий представляет компоненты контейнера, а серый — компоненты дисплея.

Компоненты контейнера — это уровень данных или логики, и вы можете использовать упомянутый выше API с отслеживанием состояния. Используя хуки жизненного цикла, вы можете напрямую подключаться к хранилищу управления состоянием, например.Redux 或 Flux, который может передавать данные и обратные вызовы соответствующим дочерним компонентам через свойства. компонент контейнераrenderВозвращаемый метод представляет собой элемент React, состоящий из нескольких подкомпонентов представления. Чтобы иметь доступ ко всем API с отслеживанием состояния, компоненты контейнера должны использовать ES6.classОбъявляйте компоненты, а не функции.

Таким образом, заявление под названиемGreetingкомпонент, он имеетstate, 一个生命周期钩子 componentDidMount() 以及 render.

class Greeting extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "",
    };
  }

  componentDidMount() {
    // AJAX
    this.setState(() => {
      return {
        name: "William",
      };
    });
  }

  render() {
    return (
      <div>
        <h1>Hello! {this.state.name}</h1>
      </div>
    );
  }
}

На данный момент компонент является компонентом с отслеживанием состояния. потому чтоGreetingКомпоненты становятся компонентами-контейнерами, которые могут разделить пользовательский интерфейс на компоненты представления, как описано ниже.

Презентационная составляющая

Компоненты дисплея могут использоватьprops, render以及 context(API без гражданства), на самом деле компонент без природы, который может быть объявлен с функцией:

const GreetingCard = (props) => {
  return (
    <div>
      <h1>Hello! {props.name}</h1>
    </div>
  )
}

Презентационный компонент принимает только данные и обратные вызовы из свойств, которые генерируются компонентом-контейнером или его родительским компонентом.

Синий представляет компоненты представления, серый представляет компоненты контейнера. Логика и представление пользовательского интерфейса инкапсулированы в контейнеры и компоненты представления соответственно, так что можно получить идеальные компоненты:


const GreetingCard = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
    </div>
  )
}

class Greeting extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "",
    };
  }

  componentDidMount() {
    // AJAX
    this.setState(() => {
      return {
        name: "William",
      };
    });
  }

  render() {
    return (
      <div>
       <GreetingCard name={this.state.name} />
      </div>
    );
  }
}

Как вы можете видеть выше, я изменил часть представления пользовательского интерфейса сGreetingПеремещен в функциональный компонент без сохранения состояния. Конечно, это всего лишь простой пример, но в основном то же самое делается и в более сложных приложениях.

Компоненты высшего порядка (HOC)

Компонент более высокого порядка — это функция, которая принимает компонент в качестве параметра и возвращает новый компонент.

Это мощный шаблон для повторного использования логики компонента для любого компонента. подобноreact-router-v4 和 Redux. существуетreact-router-v4в использованииwithRouter(), ваши компоненты могут наследовать через реквизитыreact-routerнекоторые методы в . существуетreduxТо же самое верно и вconnect({})()способactionsа такжеreducerв компонент.

Расширенный компонент представлен пунктирной линией на рисунке выше, это функция, которая возвращает новый компонент.

Взгляните на этот пример:

import {withRouter} from 'react-router-dom';

class App extends React.Component {
  constructor() {
    super();
    this.state = {path: ''}
  }
  
  componentDidMount() {
    let pathName = this.props.location.pathname;
    this.setState(() => {
      return {
        path: pathName,
      }
    })
  }
  
  render() {
    return (
      <div>
        <h1>Hi! I'm being rendered at: {this.state.path}</h1>
      </div>
    )
  }
}

export default withRouter(App);

При экспорте моих компонентов используйте react-router-v4withRouter()завернул мой компонент. Затем в хуке жизненного циклаcomponentDidMount(), пройти можноthis.props.location.pathnameОбновите значение вstate. Мой компонент получает метод react-router-v4 через реквизит. Есть много других примеров.

Рендеринг обратных вызовов

Аналогично ХОС,render callbacks 或 render propsЭто также мощный шаблон для совместного использования или повторного использования логики компонентов. Хотя все больше разработчиков склонны повторно использовать логику через HOC, есть причины и преимущества использования обратных вызовов рендеринга — однажды в Майкле Джексоне«Никогда больше не пиши другой HOC»Отличное объяснение. Есть несколько ключевых моментов: обратные вызовы рендеринга могут уменьшить конфликты пространств имен и лучше объяснить, откуда берется логика кода.

Синие пунктирные линии представляют собой обратные вызовы рендеринга.

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  increment = () => {
    this.setState(prevState => {
      return {
        count: prevState.count + 1,
      };
    });
  };

  render() {
    return (
      <div onClick={this.increment}>{this.props.children(this.state)}</div>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <Counter>
        {state => (
          <div>
            <h1>The count is: {state.count}</h1>
          </div>
        )}
      </Counter>
    );
  }
}

существуетCountкомпонентrenderвложенный вthis.props.childrenметод и поставитьthis.stateПередайте его как параметр. существуетAppкомпонент, я используюCounterзавернул его вAppможно получить вCounterметод данных и другая логика.{state => ()}это обратный вызов рендеринга. я получаю это автоматическиCounterсостояние в .

Спасибо за прочтение

Добро пожаловать всем, чтобы оставить сообщение и предложения, вышеизложенное - мое мнение о шаблоне проектирования компонентов React!

Пропсы рендера не упомянуты выше, вы можете посмотретьПример введения официального сайта

КонечноReact V16.8.0ДобавленhooksС помощью нового API компоненты с отслеживанием состояния также могут быть реализованы с помощью функций.Дополнительную информацию можно найти на официальном веб-сайте.

Наконец, я рекомендую вам следить за блогом Дэна, одного из авторов React,Напишите устойчивые компоненты4 принципа.

Если есть какие-либо ошибки или неточности, пожалуйста, обязательно исправьте их, большое спасибо!

Ссылаться на

  1. уровень up.git connect.com/react-compo…
  2. reactjs.org/