# Функция setup

В этом разделе используется синтаксис однофайловых компонентов в примерах кода

Подразумевается, что уже изучили и разобрались с разделами Введение в Composition API и Основы реактивности. Если нет — прочитайте их сначала.

# Аргументы

При использовании функции setup она будет получать два аргумента:

  1. props — входные параметры
  2. context — контекст

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

# Входные параметры

В первом аргументе setup передаются входные параметры props. Как и следует ожидать в обычном компоненте, props внутри функции setup реактивны и будут обновляться при передаче новых значений.

// MyBook.vue

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}
1
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)
}
1
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)
}
1
2
3
4
5
6
7
8
9

# Контекст

Второй аргумент, передаваемый в функцию setup, будет контекст context. Это обычный объект JavaScript через который предоставляется доступ к трём свойствам компонента:

// MyBook.vue

export default {
  setup(props, context) {
    // Атрибуты (нереактивный объект)
    console.log(context.attrs)

    // Слоты (нереактивный объект)
    console.log(context.slots)

    // Генерация событий (метод)
    console.log(context.emit)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Так как объект context будет обычным объектом JavaScript (т.е. он нереактивный), то для context можно спокойно использовать деструктуризацию ES6.

// MyBook.vue
export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}
1
2
3
4
5
6

Свойства attrs и slots — объекты с состоянием, которые всегда будут обновляться при обновлении самого компонента. Это значит, что следует избегать деструктуризации для них и всегда ссылаться на свойства как attrs.x или slots.x. Обратите внимание также, что в отличие от props, свойства attrs и slots НЕ РЕАКТИВНЫ. Если необходимо применять побочные эффекты, основанные на изменениях attrs или slots, то следует делать это внутри жизненного цикла onUpdated.

# Доступ к свойствам компонента

При выполнении setup ещё не будет создан экземпляр компонента. Поэтому можно получить доступ только к следующим свойствам:

  • props
  • attrs
  • slots
  • emit

Другими словами, не получится обратиться к следующим опциям компонента:

  • data
  • computed
  • methods

# Использование в шаблонах

Если функция 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>
1
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])
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# Использование this

Внутри setup() использование this не будет ссылкой на текущий активный экземпляр. Так как setup() вызывается до разрешения других опций компонента, то поведение this внутри setup() будет несколько отличаться от this в других опциях. Это может привести к путанице при использовании setup() совместно с другими Options API.