найти правильный слот

Я недавно заглянул на vue.js. У него много общего с реагированием, но я считаю его более доступным, то есть более легким в освоении. А разделение html на шаблоны дает то знакомое и удобное ощущение, которого я часто жажду.

Vue.js также имеет дополнительный плагин под названием Vuex. Это вводит государственное управление по типу Flux. Фактически, Vuex довольно неукоснительно следует архитектуре Flux, и, поскольку вы, возможно, помните, что я был большим поклонником Flux с давних пор, вы не удивитесь, что я настоятельно рекомендую Vuex для чего-то большего, чем самые тривиальные проекты. Я обязательно буду использовать Vuex в любое время, когда использую Vue.js.

Доказательство правила

Конечно, это означает, что я не буду использовать Vuex в этой статье! Что ж, здесь основное внимание уделяется тому, как создать компонент пользовательского интерфейса в Vue.js v2, и я не хочу отвлекаться от этого из-за какой-либо путаницы в том, что я делаю с управлением состоянием. Хотя, потратив сейчас немало слов на управление государством, вы можете почувствовать, что я уже потерпел неудачу в этом !!

Время для диалога

Итак, пришло время поговорить о создании компонента vue.js. Я решил создать компонент модального диалога для этого примера и изобретательно назвал его modal-vue.

Функциональность основана на библиотеке Elm Криса Дженкина, elm-dialog, которую я использовал в недавнем проекте. По сути, он должен принимать настраиваемый заголовок, тело и нижний колонтитул для отображения диалогового окна вместе с несколькими реквизитами для управления вещами, например, должен ли отображаться диалог или нет.

Анатомия компонента

Структура компонента vue.js проста и интуитивно понятна, с тремя отдельными частями для html, javascript и css соответственно. Сложная диаграмма ниже суммирует все это.

JavaScript для гуру

Мне нравится думать о себе как о программисте javascript, поэтому давайте начнем с javascript внутри тега <script> нашего компонента.

Это выглядит так

export default {
  props: {
    showModal: Boolean,
    closeAction: Function,
    containerClass: String
  }
}

По сути, он определяет три свойства, которые может быть передан компоненту.

  • showModal, логическое значение, определяющее, следует ли отображать модальное диалоговое окно.
  • closeAction, функция, вызываемая при нажатии кнопки закрытия диалогового окна.
  • containerClass, необязательный класс контейнера Bootstrap для <div>, который является оболочкой диалогового окна.

Это не одна из тех статей, где автор начинает с чего-то простого, а затем строит и развивает это до тех пор, пока у вас не заболеет голова. Все - в разделе <script> больше не будет!

HTML-шаблон

Вы можете использовать функцию рендеринга javascript в vue.js точно так же, как и react, но наиболее распространенный и, на мой взгляд, наиболее интуитивно понятный подход - это использование шаблона. Для этого конкретного компонента все происходит в теге <template>.

Итак, ключевая вещь, которую вы, несомненно, уже заметили, это то, что vue.js имеет собственный DSL, встроенный в теги html. И это то, чему вам нужно научиться, чтобы использовать vue.js. Но это очень просто, и если вы когда-либо использовали какой-либо другой язык атрибутов шаблонов, которых много (смею упомянуть Zope!), То вы очень легко его поймете.

Директивы Vue, js обычно начинаются с v-, например v-if в приведенной выше сути, и вы можете найти полную информацию обо всех директивах, доступных в документации Vue.js, которая является отличным ресурсом.

привязка

Начнем сверху с

<div :class="containerClass">

Хорошо, я уже здесь выпендриваюсь! :class на самом деле является сокращением от v-bind:class, но я бы с самого начала отказался от v-bind. Обычно, если вы начинаете атрибут с двоеточия :, это означает, что это динамический атрибут, и значение этого атрибута будет оцениваться как код.

Таким образом, <div :class="containerClass"> не означает, что этот div будет иметь класс CSS «containerClass». containerClass будет оцениваться как код, и, поскольку мы уже определили его как опору в нашем разделе <script>, это означает, что значение опоры containerClass, которое мы передаем компоненту, будет использоваться для класса CSS.

привязка ++

В следующей строке привязка становится немного сложнее:

<div :class="{modal: true, in: showModal}" :style="{ display: showModal ? 'block' : 'none' }">

В vue.js, когда вы привязываете объект к атрибуту class, то для каждого свойства, значение которого равно true, это свойство будет частью атрибута класса html. Таким образом, для {modal: true, in: showModal} modal всегда истинно, а in будет зависеть от значения свойства showModal. Таким образом, если showModal истинно, это разрешит и атрибут class = 'modal in'.

Для атрибута style это просто простой Javascript, и, если showModal снова будет истинным, это преобразуется в style = '{display: block}'

вставляя это в

Передача потенциально длинного форматированного HTML для заголовка, тела и нижнего колонтитула диалогового окна не подходит для передачи реквизитов в качестве атрибутов внутри тега HTML.

К счастью, у vue.js есть очень хороший способ сделать это - слоты!

Слоты очевидно смоделированы по черновой спецификации веб-компонентов W3C. Когда я впервые прочитал это, я должен признать, что у меня упало сердце. Мое впечатление о спецификации веб-компонентов W3C было таково, что это одна из тех вещей, которые были в черновике вечно - и я представил бесконечную говорящую мастерскую, в то время как остальной мир двигается дальше! Но когда я на самом деле взглянул (радикально, я знаю) на то, что они предлагают, мне показалось, что это очень хорошо !!

В любом случае, суть всего в том, что простая разметка

<slot name="header"></slot>

определяет слот для содержимого заголовка. В свое время мы рассмотрим, как передать контент в слот, но в основном тег <slot> будет заменен этим контентом.

слоты с отношением

Чтобы реализовать диалог с Bootstrap, мне нужно обернуть верхний, основной и нижний колонтитулы в div с соответствующим классом Bootstrap. Так, например, содержимое нижнего колонтитула должно быть заключено в <div class="modal-footer">.

Но подождите, нижний колонтитул является необязательным, и если нижний колонтитул не передан, я не хочу, чтобы мой компонент отображал пустой <div class="modal-footer"> - я просто хочу, чтобы нижний колонтитул не был.

К счастью, vue.js v2 предоставляет некоторые свойства экземпляра, которые позволяют вам проверять ваш компонент. Один из них - $ slots, и он позволяет вам получить доступ к значению каждого названного слота. Таким образом, this.$slot.footer вернет значение слота нижнего колонтитула. Бинго!

Таким образом, в нашем шаблоне мы можем использовать директиву v-if для рендеринга всего div <div class="modal-footer"> только в том случае, если компоненту был передан слот нижнего колонтитула. Это делается с помощью разметки:

<div v-if="this.$slots.footer" class="modal-footer">

Используя наш компонент

И, наконец, мы подошли к моменту, когда мы можем начать использовать наш новый замечательный компонент modal-vue.

Суть ниже показывает довольно упрощенный пример.

Свойство данных showModal используется для управления отображением диалогового окна и передается как свойство в теге <modal> в строке 6 вместе с опорой closeAction, которая определяет метод, вызываемый при нажатии кнопки закрытия диалогового окна. В данном случае это метод closeDialog, и все, что он делает, это устанавливает для showModal значение false (строка 26), тем самым удаляя диалог.

В этом примере заголовок и основной слот передаются в диалоговое окно для отображения, и это просто html с соответствующим атрибутом слота.

Вот и все!

дальнейшее чтение

Вы можете увидеть в действии компонент modal-vue в этом примере.

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

И, возможно, создайте и поделитесь своим собственным компонентом vue.js!