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

React.js

Шаблон проектирования компонентов React — поставщик-потребитель

Шаблоны проектирования компонентов React — Render-props

Этот режим по сути решает проблему передачи значений между компонентами. Но он более плотно инкапсулирует логику передачи по значению и некоторые внутренние манипуляции.

Сценарий: я надеюсь уменьшить передачу реквизита между верхними и нижними компонентами.Короче говоря, не нужно явно передавать значения для достижения цели взаимной связи между компонентами

Например, в некоторых интерфейсах должны быть такие компоненты, как вкладки, которые состоят из вкладок и элементов вкладки.Нажмите на каждый элемент вкладки, и элемент вкладки будет выделен. Тогда Tab и TabItem должны общаться естественным образом. Естественный способ написать это выглядит следующим образом

<TabItem active={true} onClick={this.onClick}>One</TabItem>
<TabItem active={false} onClick={this.onClick}>Two</TabItem>
<TabItem active={false} onClick={this.onClick}>Three</TabItem>

Недостатки этого очевидны:

  • Передача множества реквизитов каждый раз, когда вы используете TabItem
  • Каждый раз, когда добавляется новый TabItem, необходимо добавлять соответствующие реквизиты.
  • Если вы хотите добавить TabItem, вам нужно изменить код JSX вкладок.

Однако мы не хотим реализовывать взаимодействие между компонентами через свойства или контекст. Надеюсь, использование будет таким же кратким, как показано ниже.

    <Tabs>
      <TabItem>第一</TabItem>
      <TabItem>第二</TabItem>
      <TabItem>第三</TabItem>
    </Tabs>

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


выполнить

Как только вы поймете, какое взаимодействие должно быть достигнуто, и какой эффект должен быть достигнут на уровне кода, вы можете приступить к работе.

Компонент TabItem имеет два ключевых реквизита: active (указывает, следует ли подсвечивать текущий), onTabClick (функция обратного вызова, вызываемая при нажатии), Поскольку TabItem является контейнером каждой вкладки, он отвечает только за рендеринг props.children, поэтому можно использовать функциональные компоненты.

export const TabItem = props => {
  const { active, onTabClick, children } = props
  const style = {
    color: active ? 'red' : 'green',
    cursor: 'pointer'
  }
  return <>
    <h1 style={style} onClick={onTabClick}>
      {children}
    </h1>
  </>
}

Давайте еще раз посмотрим на результаты, которые мы получили:

    <Tabs>
      <TabItem>第一</TabItem>
      <TabItem>第二</TabItem>
      <TabItem>第三</TabItem>
    </Tabs>

Недостатком передачи реквизита является то, что его следует избегать при использовании компонентов, так куда же его передавать? Естественно, это компонент Tabs. Но нет реквизита, переданного выше. Хотя табы могут получить доступ к дочерним элементам в пропсах, дети в руке уже готовы, если вы измените его напрямую, будут проблемы. Если нет возможности напрямую изменить дочерние элементы, мы сделаем копию дочерних элементов, а затем изменим скопированные дочерние элементы, а затем отрендерим их, и все будет в порядке!

Давайте посмотрим на реализацию вкладок:

class Tabs extends React.Component {
  state={
    activeIndex: 0
  }
  render() {
    const { activeIndex } = this.state
    const newChildren = React.Children.map(this.props.children, (child, index) => {
      if (child.type) {
          // 复制并修改children
        return React.cloneElement(child, {
          active: activeIndex === index,
          onTabClick: () => this.setState({activeIndex: index})
        })
      } else {
        return child
      }
    })
    return <div className="tabs">
      {newChildren}
    </div>
  }
}

Здесь вам нужно использовать API, которые обычно не используются в React:

  • React.Children.map
  • React.cloneElement

использоватьReact.Children.mapпройти реквизит.дет.

а такжеReact.cloneElementВы можете скопировать элемент, первый параметр — это копируемый элемент, а вторым параметром мы можем добавить реквизиты, которые мы хотим передать, то есть время. Переходим в актив и onTabClick. добиться конечного эффекта.

Суммировать

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