Главная Блог Понимание компонентов без состояния в Vue

Понимание компонентов без состояния в Vue

Понимание компонентов без состояния в Vue

Введение - что такое состояние приложения и зачем оно нам нужно?

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

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

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

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

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

Vue и компоненты без состояния (функциональные)

Компоненты без состояния в Vue - это не что иное, как функциональные компоненты. Но каковы функциональные компоненты? Чтобы ответить на это, мы сначала должны понять, что такое функциональное программирование.

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

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

Таким образом, функциональный компонент - это компонент без состояния и возможность его изменения. Вывод, который он предоставляет, всегда (и только) основан на заданном вводе. С точки зрения Vue, этот вид компонента будет давать различный вывод в зависимости от заданного реквизита.

Синтаксис

Vue имеет простой способ определения функционального компонента. Все, что нам нужно сделать, это настроить ключ с именем functional . Мы можем сделать это либо в шаблоне (если мы создаем однофайловый компонент), либо в разделе скрипта, например:

 <template functional>
     <div>
        Hi from functional/stateless component
     </div>
 </template> 

или же

export default {
  functional: true,
  props: {
    // ...
  },
  render(createElement, context) {
    return createElement(
      'div', 'Hi from functional/stateless component'
    );
  }
};

В последней версии Vue мы можем опустить props в разделе скриптов, и все атрибуты, найденные в компоненте, будут преобразованы в реквизиты.

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

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

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

Вместо этого все, что нужно компоненту, предоставляется через context . В функции рендеринга он передается как дополнительный 2-й аргумент после `createElement`.

Официальная документация гласит, что context - это объект, содержащий:

  • props : объект предоставленных реквизита
  • children : массив детей VNode
  • slots : функция, возвращающая объект slots
  • scopedSlots : (2.6.0+) Объект, который предоставляет переданные области слотов. Также выставляет нормальные слоты как функции.
  • data : весь объект данных, переданный компоненту как второй аргумент `createElement`.
  • parent : ссылка на родительский компонент.
  • listeners : (2.3.0+) Объект, содержащий зарегистрированных родителей слушателей событий. Это псевдоним data.on
  • injections : (2.3.0+), если используется опция инъекции, она будет содержать разрешенные инъекции.

Зачем нам нужны компоненты без состояния?

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

Что это означает с точки зрения их использования?

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

Далее, простое отображение списка данных было бы хорошим примером функционального компонента ...

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

Пример

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

export default {
    name: 'panel',
    functional: true,
    props: {
        title: String
    },
    render(createElement, context) {
        const slots = context.slots();
        const header = createElement('header', {
            attrs: {
                class: 'panel-header'
            }
        }, context.props.title);
        const body = createElement('main', {
            attrs: {
                class: 'panel-body'
            }
        }, slots.default);
        return createElement('section', {
            attrs: {
                class: 'panel'
            }
        }, [header, body]);
    }
}

Как уже упоминалось, единственной целью этого компонента является создание стиля панели (карты). Он будет иметь header и main элементы, которые будут содержать заголовок панели и содержимое HTML соответственно.

Вся магия делается внутри функции render с помощью аргумента `createElement`. `createElement` является частью системы Virtual Dom , реализованной в ядре Vue. Учитывая, что Virtual DOM здесь не является темой, и если вы хотите вникнуть в подробности, ниже приведены ссылки на официальную документацию.

Панель CSS выглядит следующим образом:

.panel {
    margin-bottom: .5rem
}

.panel, .panel-header {
    border: 1px solid #d3d3d3;
    border-radius: 4px;
}

.panel-header, .panel-body, .panel {
    padding: .5rem;
}

.panel-header {
    background-color: #efefef;
    color: #eeeee
}

Это простой, простой CSS-код, обеспечивающий некоторые отступы и цвета.

Дочерние компоненты

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

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

Компонент списка:

  • export default { name: 'cars', props: { data: Array } } шаблон:
<template>
    <ul>
        <li v-for="car in data" :key="car">{{car}}
        </li>
    </ul>
</template>

Простой текстовый компонент:

export default { name: 'lorem-ipsum' } 

шаблон:

 <template> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </template> 

На этом этапе, с доступными дочерними компонентами, все, что нам нужно сделать, это обернуть их в нашем приложении компонентом панели следующим образом:

<div class="vue-app">
    <panel :title="'Car Manufacturers'">
        <cars :data="['Mazda', 'Ford', 'Mercedes']">
        </cars>
    </panel>
    <panel :title="'Lorem Ipsum'">
            <lorem-ipsum>
            </lorem-ipsum>
    </panel> 
</div>

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

Vue Panel Functional Component @ Code Pen

Заключение

Между разработчиками идут большие дебаты, почти такие же интенсивные, как дебаты Vue против React против Angular. Эта дискуссия известна как функциональное программирование против ООП.

источник
иллюстрация