Руководство
Основы
- Установка
- Введение
- Экземпляр 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
:
|