# Функция setup
В этом разделе используется синтаксис однофайловых компонентов в примерах кода
Подразумевается, что уже изучили и разобрались с разделами Введение в Composition API и Основы реактивности. Если нет — прочитайте их сначала.
# Аргументы
При использовании функции setup
она будет получать два аргумента:
props
— входные параметрыcontext
— контекст
Разберёмся подробнее с тем, как можно использовать каждый из аргументов.
# Входные параметры
В первом аргументе setup
передаются входные параметры props
. Как и следует ожидать в обычном компоненте, props
внутри функции setup
реактивны и будут обновляться при передаче новых значений.
// MyBook.vue
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
2
3
4
5
6
7
8
9
10
ВНИМАНИЕ
Поскольку props
реактивны, то нельзя использовать деструктуризацию ES6, потому что это уберёт реактивность со входных параметров.
Если необходимо выполнить деструктуризацию входных параметров, то это можно сделать с помощью toRefs внутри функции setup
:
// MyBook.vue
import { toRefs } from 'vue'
setup(props) {
const { title } = toRefs(props)
console.log(title.value)
}
2
3
4
5
6
7
8
9
Если, например, title
необязательный входной параметр, то он может отсутствовать в props
. В этом случае toRefs
не создаёт ссылку для title
и вместо него потребуется воспользоваться toRef
:
// MyBook.vue
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
console.log(title.value)
}
2
3
4
5
6
7
8
9
# Контекст
Второй аргумент, передаваемый в функцию setup
, будет контекст context
. Это обычный объект JavaScript через который предоставляется доступ к другим значениям, полезным внутри setup
:
// MyBook.vue
export default {
setup(props, context) {
// Атрибуты (нереактивный объект, эквивалент $attrs)
console.log(context.attrs)
// Слоты (нереактивный объект, эквивалент $slots)
console.log(context.slots)
// Генерация событий (функция, эквивалент $emit)
console.log(context.emit)
// Объявленные публичные свойства (функция)
console.log(context.expose)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Так как объект context
будет обычным объектом JavaScript (т.е. он нереактивный), то для context
можно спокойно использовать деструктуризацию ES6.
// MyBook.vue
export default {
setup(props, { attrs, slots, emit, expose }) {
...
}
}
2
3
4
5
6
Свойства attrs
и slots
— объекты с состоянием, которые всегда будут обновляться при обновлении самого компонента. Это значит, что следует избегать деструктуризации для них и всегда ссылаться на свойства как attrs.x
или slots.x
. Обратите внимание также, что в отличие от props
, свойства attrs
и slots
НЕ РЕАКТИВНЫ. Если необходимо применять побочные эффекты, основанные на изменениях attrs
или slots
, то следует делать это внутри жизненного цикла onBeforeUpdate
.
Роль expose
рассмотрим в ближайшее время.
# Доступ к свойствам компонента
При выполнении setup
можно получить доступ только к следующим свойствам:
props
attrs
slots
emit
Другими словами, не получится обратиться к следующим опциям компонента:
data
computed
methods
refs
(ссылки на элементы шаблона)
# Использование в шаблонах
Если функция setup
возвращает объект, то его свойства также будут доступны в шаблоне компонента, как и свойства props
, передаваемые в setup
:
<!-- MyBook.vue -->
<template>
<div>{{ collectionName }}: {{ readersNumber }} {{ book.title }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
props: {
collectionName: String
},
setup(props) {
const readersNumber = ref(0)
const book = reactive({ title: 'Руководство Vue 3' })
// всё объявленное будет доступно в шаблоне
return {
readersNumber,
book
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Запомните, возвращаемые из setup
refs при обращениях в шаблоне автоматически неглубоко разворачиваются, поэтому указывать .value
в шаблоне не требуется.
# Использование в render-функциях
Функция setup
может также возвращать render-функцию, которая сможет использовать реактивное состояние, объявленное в той же области видимости:
// MyBook.vue
import { h, ref, reactive } from 'vue'
export default {
setup() {
const readersNumber = ref(0)
const book = reactive({ title: 'Руководство Vue 3' })
// Обратите внимание, здесь потребуется явно использовать значение ref
return () => h('div', [readersNumber.value, book.title])
}
}
2
3
4
5
6
7
8
9
10
11
12
Возвращение render-функции, не позволяет возвращать что-либо ещё. Внутри компонента это не проблема, но могут быть сложности, если нужно объявить методы этого компонента, которые могут использоваться родительским компонентом через ссылки в шаблоне.
Эту проблему можно решить с помощью вызова expose
, передав в него объект со свойствами, которые должны быть доступны для экземпляра внешнего компонента:
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0)
const increment = () => ++count.value
expose({
increment
})
return () => h('div', count.value)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Теперь метод increment
доступен в родительском компоненте через ссылку в шаблоне.
# Использование this
Внутри setup()
использование this
не будет ссылкой на текущий активный экземпляр. Так как setup()
вызывается до разрешения других опций компонента, то поведение this
внутри setup()
будет несколько отличаться от this
в других опциях. Это может привести к путанице при использовании setup()
совместно с другими Options API.