Подробно объясните разницу и применение компонентов дисплея и компонентов контейнера.

внешний интерфейс Flux React.js дизайнер

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

Давайте сначала рассмотрим пример компонента контейнера и компонента представления вместе.

class TodoList extends React.Component{
    constructor(props){
        super(props);
        this.state ={
            todos:[]
        }
        this.fetchData = this.fetchData.bind(this);
    }
    componentDidMount(){
        this.fetchData();
    }
    fetchData(){
        fetch('/api/todos').then(data =>{
            this.setState({
                todos:data
            })
        })
    }
    render(){
        const {todos} = this.state;
        return (<div>
                <ul>
                    {todos.map((item,index)=>{
                        return <li key={item.id}>{item.name}</li>
                    })}
                </ul>
            </div>)
    }
}

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

Конкретный код выглядит следующим образом:

//展示组件
class TodoList extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        const {todos} = this.props;
        return (<div>
                <ul>
                    {todos.map((item,index)=>{
                        return <li key={item.id}>{item.name}</li>
                    })}
                </ul>
            </div>)
    }

//容器组件
class TodoListContainer extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            todos:[]
        }
        this.fetchData = this.fetchData.bind(this);
    }
    componentDidMount(){
        this.fetchData();
    }
    fetchData(){
        fetch('/api/todos').then(data =>{
            this.setState({
                todos:data
            })
        })
    }
    render(){
        return (<div>
                <TodoList todos={this.state.todos} />    
            </div>)
    }
}

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

Презентационный компонент

  1. Обратите внимание на эффект отображения (внешний вид) страницы
  2. Внутренние компоненты и контейнеры могут включать компоненты отображения, обычно содержащие некоторые собственные теги DOM и стиль (стиль).
  3. Обычно разрешается включать другие компоненты через this.props.children.
  4. Нет никаких зависимостей от других частей приложения, таких как операции или хранилища Flux.
  5. Неважно, как данные загружаются и изменяются.
  6. Вы можете получать данные и выполнять операции обратного вызова только через реквизиты.
  7. Редко имеет собственное состояние, даже если оно есть, оно используется для отображения состояния пользовательского интерфейса.
  8. Будет написан как функциональный компонент, если компонент не нуждается в собственном состоянии, жизненном цикле или некоторой оптимизации производительности.
Пример:

Страница, Заголовок, Боковая панель, Информация о пользователе, Список

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

  1. Сосредоточьтесь на том, как работает приложение
  2. Inside может содержать компоненты-контейнеры и компоненты представления, но обычно не имеет собственной разметки DOM, за исключением некоторых разделов-оболочек, и никогда не имеет стилей.
  3. Предоставляйте данные и поведение другим презентационным или контейнерным компонентам.
  4. Вызывайте операции Flux и предоставляйте их в качестве обратных вызовов компонентам представления.
  5. имеют тенденцию к сохранению состояния, поскольку они, как правило, действуют как источники данных
  6. Обычно создается с использованием компонентов более высокого порядка, таких как connect() React Redux, createContainer() Relay или Container.create() Flux Utils, а не пишется вручную.
Example:

UserPage, FollowersSidebar, StoryContainer, FollowedUserList

преимущество

  1. Лучшее разделение компонентов представления и контейнера для лучшего понимания приложения и пользовательского интерфейса.
  2. Компоненты представления с высокой степенью повторного использования могут использоваться для нескольких различных источников данных.
  3. Презентационные компоненты — это ваши палитры, и вы можете поместить их на отдельные страницы и позволить дизайнерам настраивать пользовательский интерфейс, не затрагивая приложение.
  4. Это заставляет вас извлекать «компоненты макета», такие как боковые панели, страницы, контекстные меню и т. д., и использовать this.props.children вместо дублирования одной и той же разметки и макета в нескольких компонентах-контейнерах.

При введении в сборку контейнера

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

Это процесс рефакторинга, так что это лучше, чем делать все правильно с первого раза. когда вы попробуете этот режим. У вас будет интуитивное представление о том, когда его следует извлечь как компонент контейнера. как если бы вы знали, когда извлечь функцию

дихотомия

Важно, чтобы вы понимали, что разница между компонентами-контейнерами и компонентами представления — не техническая разница, а разница в назначении.

Напротив, вот несколько связанных (но разных) технических различий:

  1. С состоянием и без гражданства:

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

  2. Классы [Classes] и функции [Functions]:

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

//我们将上边的展示组件改写成函数组件可以如下
function TodoList(props){
    return (<div>
              <ul>
                    {props.todos.map((item,index)=>{
                        return <li key={item.id}>{item.name}</li>
                    })}
                </ul>  
        </div>)
}

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

  1. Чистый 【Чистый】 и Нечистый 【Нечистый】:

    Чистый: выводит то, что вводится, и не будет вносить в него соответствующие изменения. Могут быть определены как класс или функция, могут быть без сохранения состояния или с сохранением состояния. Еще одним важным аспектом чистых компонентов является то, что они не зависят от глубоких изменений свойств или состояния, поэтому производительность их рендеринга можно контролировать с помощью хука shouldComponentUpdate(). по сравнению с оптимизацией, в настоящее время только классы могут определять метод shouldComponentUpdate().

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

Когда это не важно или трудно различить, не принимайте разделение компонентов контейнера и компонентов представления как догму, Если вы не уверены, является ли компонент компонентом-контейнером или презентационным компонентом, пока не разделяйте его и пишите как презентационный компонент.

Источник перевода: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0