Руководство
Основы
- Установка
- Введение
- Экземпляр Vue
- Синтаксис шаблонов
- Вычисляемые свойства и слежение
- Работа с классами и стилями
- Условная отрисовка
- Отрисовка списков
- Обработка событий
- Работа с формами
- Основы компонентов
Продвинутые компоненты
- Регистрация компонентов
- Входные параметры
- Пользовательские события
- Слоты
- Динамические и асинхронные компоненты
- Обработка крайних случаев
Переходы и анимации
- Анимирование списков и появления/исчезновения
- Анимирование переходов между состояниями
Переиспользование и композиция
- Примеси
- Пользовательские директивы
- Render-функции и JSX
- Плагины
- Фильтры
Инструментарий
- Однофайловые компоненты
- Тестирование
- Поддержка TypeScript
- Публикация на production
Масштабирование
- Роутинг
- Управление состоянием приложения
- SSR. Отрисовка на стороне сервера
- Безопасность
Продвинутые темы
- Подробно о реактивности
Вопросы миграции
- Миграция с Vue 1.x
- Миграция с Vue Router 0.7.x
- Миграция с Vuex 0.6.x на 1.0
Мета
- Сравнение с другими фреймворками
- Присоединяйтесь к сообществу Vue.js!
- Познакомьтесь с командой
Эта документация для версий v2.x и ранее. Для v3.x, документация на русском здесь.
Слоты
Подразумевается, что вы уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.
В версии 2.6.0 был представлен новый единый синтаксис (директива
v-slot) для именованных слотов и слотов с ограниченной областью видимости. Он заменяет атрибутыslotиslot-scope, которые в настоящий момент объявлены устаревшими, но _не_ удалены и документированы здесь. Обоснование введения нового синтаксиса описано в этом RFC.
Содержимое слота
Vue реализует API распределения контента, вдохновлённое текущим черновиком спецификации веб-компонентов, используя элемент <slot> в качестве точек распространения контента.
Например, это позволит составлять такие компоненты:
|
Для этого шаблон <navigation-link> должен быть, например, таким:
|
При отрисовке компонента <slot></slot> будет заменён на «Ваш профиль». Слоты могут содержать любой код шаблона, в том числе HTML:
|
Или даже другие компоненты:
|
Если шаблон <navigation-link> не содержит элемент <slot>, любой переданный контент будет просто проигнорирован.
Область видимости при компиляции
Если необходимо использовать данные внутри слота, например:
|
То этот слот имеет доступ к тем же свойствам экземпляра (т.е. к той же «области видимости»), что и остальная часть шаблона. Слот не имеет доступа к области видимости <navigation-link>. Поэтому попытка получить url не сработает:
|
Как правило, достаточно запомнить что:
Всё в родительском шаблоне компилируется в области видимости родительского компонента; всё в дочернем шаблоне компилируется в области видимости дочернего компонента.
Содержимое слота по умолчанию
Бывает полезным указать запасное содержимое слота (т.е. по умолчанию), которое будет отображаться только тогда, когда ничего не передавалось в слот. Например, в компоненте <submit-button>:
|
Было бы удобно, если бы текст «Отправить» отображался внутри <button> большую часть времени. Чтобы сделать «Отправить» в качестве содержимого по умолчанию, необходимо поместить его между тегами <slot>:
|
Теперь при использовании <submit-button> в родительском компоненте и не указывая содержимое для слота:
|
отобразится содержимое по умолчанию — «Отправить»:
|
Но если указать содержимое:
|
Тогда оно будет использовано для отображения:
|
Именованные слоты
Обновлено в версии 2.6.0+. Устаревший синтаксис с использованием атрибута
slotможно посмотреть здесь.
Зачастую удобно иметь несколько слотов. К примеру, для компонента <base-layout> со следующим шаблоном:
|
В таких случаях элементу <slot> можно указать специальный атрибут name, который используется для определения дополнительных слотов:
|
Обычный <slot> без name неявно имеет имя «default».
Чтобы указать содержимое для именованного слота, нужно использовать директиву v-slot на <template>, передав имя слота аргументом v-slot:
|
Теперь всё внутри элементов <template> будет передаваться в соответствующие слоты. Предполагается, что любое содержимое, не обёрнутое в <template> с использованием v-slot, предназначается для слота по умолчанию.
Однако, можно и явно обернуть в <template> содержимое слота по умолчанию:
|
В обоих случаях итоговый HTML будет таким:
|
Обратите внимание, что v-slot можно добавлять только на <template> (за одним исключением), в отличие от устаревшего атрибута slot.
Слоты с ограниченной областью видимости
Обновлено в версии 2.6.0+. Устаревший синтаксис, с использованием атрибута
slot-scopeможно посмотреть здесь.
Иногда для содержимого слота полезно иметь возможность использовать данные, доступные только в дочернем компоненте. Например, представьте компонент <current-user> со следующим шаблоном:
|
Может потребоваться заменить это содержимое по умолчанию, например, чтобы отобразить имя пользователя, а не фамилию:
|
Однако это не сработает, потому что только компонент <current-user> имеет доступ к user, а новое содержимое слота отрисовывается в родительском.
Чтобы сделать user доступным для содержимого слота в родительском компоненте, необходимо добавить привязку user в качестве атрибута на элементе <slot>:
|
Атрибуты, привязанные к элементу <slot>, называются входными параметрами слота. Теперь в родительской области видимости можно использовать v-slot со значением, чтобы указать имя для предоставленных слоту входных параметров:
|
В этом примере мы выбрали имя объекта slotProps, содержащего все входные параметры слота, но можно использовать любое другое, которое нравится.
Сокращённый синтаксис для одиночного слота по умолчанию
В случаях, когда только слоту по умолчанию предоставляется содержимое, тег компонента можно использовать в качестве шаблона слота. Это позволяет использовать v-slot непосредственно на компоненте:
|
Эту запись можно сократить ещё больше. Предполагается, что не указанное явно содержимое относится к слоту по умолчанию, так и v-slot без аргумента означает слот по умолчанию:
|
Обратите внимание, что такой сокращённый синтаксис для слота по умолчанию нельзя смешивать с именованными слотами, потому что это приведёт к неоднозначности области видимости:
|
При наличии нескольких слотов лучше используйте полный синтаксис на основе <template> для всех слотов:
|
Деструктурирование входных параметров слота
Слоты с ограниченной областью видимости под капотом работают, заключая содержимое слота в функцию и передавая входные параметры одним аргументом:
|
Это значит, что значение v-slot может принимать любое допустимое выражение JavaScript, которое может появиться в позиции аргумента определения функции. Поэтому в поддерживаемых окружениях (однофайловых компонентах или современных браузерах) можно также использовать деструктурирование ES2015, чтобы извлекать определённые входные параметры слотов, например, вот так:
|
Такой подход сделает шаблон намного чище, особенно когда слот предоставляет множество входных параметров. Это также открывает другие возможности, такие как переименование входных параметров, например, user в person:
|
Можно даже определять значения по умолчанию, которые будут использоваться в случае, если входной параметр слота не определён:
|
Динамическое имя слота
Добавлено в версии 2.6.0+
Динамические аргументы директивы также работают с v-slot, что позволяет указать динамическое имя слота:
|
Сокращённая запись для именованных слотов
Добавлено в версии 2.6.0+
Аналогично v-on и v-bind, у v-slot есть собственное сокращение, заменяющее всё перед аргументом (v-slot:) специальным символом #. Например, v-slot:header можно записать как #header:
|
Однако, как и в случае с другими директивами, сокращение доступно только при наличии аргумента. Это означает, что следующий синтаксис недопустим:
|
Необходимо всегда указывать имя слота, если хотите использовать сокращение:
|
Другие примеры
Входные параметры слотов позволяют превратить их в переиспользуемые шаблоны, которые могут отображать различное содержимое, основываясь на входных параметрах. Это очень полезно при разработке переиспользуемых компонентов, которые инкапсулируют логику данных, позволяя родительскому компоненту настраивать часть своего шаблона.
Например, реализуем компонент <todo-list>, который содержит шаблон и логику фильтрации для списка задач:
|
Вместо жёсткого кодирования содержимого каждой задачи списка, мы можем позволить родительскому компоненту взять на себя управление отображением с помощью слота, а затем привязать todo в качестве входного параметра слота:
|
Теперь при использовании <todo-list> можно опционально переопределить <template> для элементов списка, но сохранить доступ к данным из дочернего компонента:
|
Однако, это едва ли не вершина айсберга возможностей, на которые способны слоты с ограниченной областью видимости. Несколько реальных примеров использования слотов с ограниченной областью видимости можно посмотреть в библиотеках Vue Virtual Scroller, Vue Promised и Portal Vue.
Устаревший синтаксис
В версии Vue 2.6.0 была представлена директива
v-slot, предлагающая улучшенный альтернативный API для всё ещё поддерживаемых атрибутовslotиslot-scope. Полное обоснование добавленияv-slotописано в RFC. Атрибутыslotиslot-scopeбудут поддерживаться в новых версиях 2.x, но официально они считаются устаревшими и будут удалены во Vue 3.
Именованные атрибуты с помощью атрибута slot
Устаревшее с 2.6.0+. Новый рекомендованный синтаксис можно посмотреть здесь.
Для передачи содержимого в именованные слоты из родительского компонента используйте специальный атрибут slot на теге <template> (в качестве примера здесь используется компонент <base-layout>, описанный выше):
|
Также атрибут slot можно использовать непосредственно на обычном элементе:
|
Может быть только один слот без имени, который является слотом по умолчанию и служит для отображения оставшегося содержимого. В обоих случаях итоговый HTML будет таким:
|
Слоты с ограниченной областью видимости с помощью атрибута slot-scope
Устаревшее с 2.6.0+. Новый рекомендованный синтаксис можно посмотреть здесь.
Для получения входных параметров, переданных в слот, родительский компонент может использовать <template> с атрибутом slot-scope (в качестве примера используется <slot-example>, описанный выше):
|
Здесь slot-scope объявляет объект с полученными входными параметрами как переменную slotProps и делает его доступным внутри области видимости <template>. Можно назвать slotProps как угодно, придерживаясь именования аргументов для функций в JavaScript.
В примере slot="default" можно опустить, так как это подразумевается:
|
Атрибут slot-scope также можно использовать непосредственно не только на элементах <template> (включая компоненты):
|
Значение slot-scope может принимать любое допустимое выражение JavaScript, которое может использоваться в позиции аргумента определения функции. Это означает, что в поддерживаемых средах (однофайловых компонентах или современных браузерах) также можно использовать деструктурирование ES2015 в выражении, например, так:
|
Используя <todo-list>, описанный выше в качестве примера, вот эквивалентная запись с использованием slot-scope:
|