# Композиция
# mixins
Тип:
Array<Object>
Подробности:
Опция
mixins
принимает массив объектов примесей. Эти объекты могут содержать опции экземпляра, как и обычные объекты экземпляра, и они будут объединены в окончательный набор опций с использованием специальной логики объединения. Например, если хукcreated
указан в примеси и есть в компоненте, то будут вызваны обе функции.Хуки в примесях вызываются в порядке их определения до вызова собственных хуков компонента.
Информация
Во Vue 2, примеси были основным механизмом для создания многократно используемых фрагментов логики компонентов. Хотя примеси продолжают поддерживаться во Vue 3, теперь Composition API является предпочтительным подходом для повторного использования кода между компонентами.
Пример:
const mixin = { created() { console.log(1) } } createApp({ created() { console.log(2) }, mixins: [mixin] }) // => 1 // => 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15См. также: Примеси
# extends
Тип:
Object
Подробности:
Позволяет одному компоненту расширять другой, наследуя его опции.
С точки зрения реализации,
extends
очень похож наmixins
. Компонент, указанный с помощьюextends
, будет рассматриваться так же, как если бы он был первой примесью.Однако
extends
иmixins
преследуют разные цели. Опцияmixins
в основном используется для компоновки функциональных блоков, в то время какextends
в основном связана с наследованием.Как и в случае с
mixins
, любые опции будут объединены с использованием соответствующей стратегии объединения.Пример:
const CompA = { ... } const CompB = { extends: CompA, ... }
1
2
3
4
5
6
# provide / inject
Тип:
- provide:
Object | () => Object
- inject:
Array<string> | { [key: string]: string | Symbol | Object }
- provide:
Подробности:
Эта пара опций используется вместе, чтобы позволить компоненту-родителю внедрять зависимости во все компоненты-потомки. Не имеет значения, насколько глубоко в иерархии они находятся, пока располагаются в той же самой родительской цепочке. Если знакомы с React, то это очень похоже на функцию
context
.Опция
provide
должна быть объектом или функцией, возвращающей объект. Этот объект содержит свойства, которые после внедрения будут доступны в потомках. Можно использовать ES2015 Symbols в качестве ключей объекта, но только в окружениях, которые нативно поддерживаютSymbol
иReflect.ownKeys
.Опция
inject
должна быть:- массивом строк;
- или объектом, где ключами являются локальные имена привязки, а значением может быть:
- ключ (строка или Symbol) для поиска в доступных внедрениях;
- объект, в котором
- свойство
from
является ключом (строка или Symbol) для поиска в доступных внедрениях, - свойство
default
используется в качестве запасного значения.
- свойство
Примечание: привязки
provide
иinject
НЕ РЕАКТИВНЫ. Так сделано специально. Однако, если передать реактивный объект, то его свойства останутся реактивными.Пример:
// родительский компонент предоставляет доступ к 'foo' const Provider = { provide: { foo: 'bar' } // ... } // дочерний компонент внедряет 'foo' для использования const Child = { inject: ['foo'], created() { console.log(this.foo) // => "bar" } // ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Работа с функциями
provide
и объектомinject
с использованием ES2015 Symbols:const s = Symbol() const Provider = { provide() { return { [s]: 'foo' } } } const Child = { inject: { s } // ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14Использование внедряемого значения для входного параметра в качестве значения по умолчанию:
const Child = { inject: ['foo'], props: { bar: { default() { return this.foo } } } }
1
2
3
4
5
6
7
8
9
10Использование внедряемого значения в качестве данных:
const Child = { inject: ['foo'], data() { return { bar: this.foo } } }
1
2
3
4
5
6
7
8Инъекции можно указывать с собственным значением по умолчанию:
const Child = { inject: { foo: { default: 'foo' } } }
1
2
3
4
5Для внедрения значение из свойства под другим именем можно использовать опцию
from
для определения свойства-источника:const Child = { inject: { foo: { from: 'bar', default: 'foo' } } }
1
2
3
4
5
6
7
8Как и для значений по умолчанию входных параметров, для не-примитивных значений необходимо использовать фабричную функцию:
const Child = { inject: { foo: { from: 'bar', default: () => [1, 2, 3] } } }
1
2
3
4
5
6
7
8См. также: Provide / Inject
# setup
- Тип:
Function
Функция setup
— новая опция компонента. Она будет стартовой точкой для использования Composition API внутри компонентов.
Время вызова
Функция
setup
вызывается сразу после первичного разрешения входных параметров, когда создаётся экземпляр компонента. В жизненном цикле вызов будет перед хуком beforeCreate.Использование с шаблонами
Если
setup
возвращает объект, его свойства будут объединены в контексте отрисовки для шаблона компонента:<template> <div>{{ count }} {{ object.foo }}</div> </template> <script> import { ref, reactive } from 'vue' export default { setup() { const count = ref(0) const object = reactive({ foo: 'bar' }) // предоставляем доступ в шаблоне return { count, object } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Обратите внимание, что refs, возвращаемые из
setup
, автоматически разворачиваются при обращениях в шаблоне. Поэтому нет необходимости указывать.value
в шаблонах.Использование с render-функциями / JSX
Функция
setup
также может возвращать render-функцию, которая может напрямую использовать реактивное состояние, объявленное в той же области видимости:import { h, ref, reactive } from 'vue' export default { setup() { const count = ref(0) const object = reactive({ foo: 'bar' }) return () => h('div', [count.value, object.foo]) } }
1
2
3
4
5
6
7
8
9
10Аргументы
Первым аргументом функция принимает разрешённые входные параметры:
export default { props: { name: String }, setup(props) { console.log(props.name) } }
1
2
3
4
5
6
7
8Обратите внимание, что объект
props
является реактивным — т.е. он обновляется при передаче новых значений входных параметров. Это позволяет его отслеживать и реагировать на изменения с помощьюwatchEffect
илиwatch
:export default { props: { name: String }, setup(props) { watchEffect(() => { console.log(`Имя: ` + props.name) }) } }
1
2
3
4
5
6
7
8
9
10НЕ ИСПОЛЬЗУЙТЕ деструктуризацию для объекта
props
, потому что это приведёт к потере его реактивности:export default { props: { name: String }, setup({ name }) { watchEffect(() => { console.log(`Имя: ` + name) // Реактивности уже не будет! }) } }
1
2
3
4
5
6
7
8
9
10Объект
props
иммутабелен для пользовательского кода в процессе разработки (будет выводиться предупреждение при попытке его изменять).Второй аргумент предоставляет объект с контекстом, который позволяет получить доступ к различным объектам и функциям, полезным внутри
setup
:const MyComponent = { setup(props, context) { context.attrs context.slots context.emit context.expose } }
1
2
3
4
5
6
7
8attrs
,slots
иemit
являются эквивалентами свойств экземпляра$attrs
,$slots
и$emit
соответственно.Свойства
attrs
иslots
являются прокси для соответствующих значений экземпляра внутреннего компонента. Это гарантирует, что они всегда содержат актуальные значения даже после обновления, чтобы была возможность уничтожать их, не беспокоясь о доступе по устаревшей ссылке:const MyComponent = { setup(props, { attrs }) { // функция, которая может вызываться где-то позднее function onClick() { console.log(attrs.foo) // гарантированно будет актуальной ссылкой } } }
1
2
3
4
5
6
7
8В версии Vue 3.2 добавлена
expose
— функция, позволяющая объявить определённые свойства через публичный экземпляр компонента. По умолчанию, публичный экземпляр, полученный с помощью$refs
,$parent
или$root
эквивалентен внутреннему экземпляру, используемому шаблоном. При вызовеexpose
будет создан отдельный публичный экземпляр с объявленными свойствами:const MyComponent = { setup(props, { expose }) { const count = ref(0) const reset = () => count.value = 0 const increment = () => count.value++ // Только метод reset будет доступен извне, например через $refs expose({ reset }) // Внутри у шаблона будет доступ к count и increment return { count, increment } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Есть ряд причин, почему
props
указываются в качестве отдельного первого аргумента, а не включаются в контекст:Гораздо чаще компонент использует
props
, чем какие-либо другие свойства. Очень часто компонент использует толькоprops
.Наличие
props
в качестве отдельного аргумента облегчает вывод их типов, без путаницы с типами других свойств в контексте. Это также позволяет сохранить консистентную сигнатуру междуsetup
,render
и простыми функциональными компонентами с поддержкой TSX.
См. также: Composition API