# Изменения функциональных компонентов
кардинальное изменение

# Обзор

Краткий обзор того, что изменилось:

  • Выигрыш по производительности функциональных компонентов в 2.x пренебрежительно мал в 3.x, поэтому рекомендуется просто использовать компоненты с состоянием
  • Функциональные компоненты могут создаваться только с помощью простых функций, которые получают аргументами props и context (т.е., slots, attrs, emit)
  • КАРДИНАЛЬНОЕ ИЗМЕНЕНИЕ: удалён атрибут functional для <template> однофайловых компонентов (SFC)
  • КАРДИНАЛЬНОЕ ИЗМЕНЕНИЕ: удалена опция { functional: true } в компонентах, создаваемых функциями

Для получения дополнительной информации читайте дальше!

# Введение

Во Vue 2 функциональные компоненты в основном использовались в двух случаях:

  • для оптимизации производительности, потому что инициализировались быстрее, чем компоненты с состоянием
  • для возможности возвращать несколько корневых узлов из компонента

Однако, во Vue 3 производительность компонентов с состоянием улучшилась до такой степени, что разница стала пренебрежительно мала. Кроме того, компоненты с состоянием теперь получили возможность возвращать несколько корневых узлов.

В результате, единственная оставшаяся причина для функциональных компонентов — простые компоненты, такие как компонент для создания динамического заголовка. В остальных случаях рекомендуется использовать компоненты с состоянием, как обычно.

# Синтаксис в 2.x

Компонент <dynamic-heading>, отвечающий за отрисовку соответствующего заголовка (т.е., h1, h2, h3, и т.д.), можно записать однофайловым компонентом в 2.x так:

<!-- Пример функционального компонента во Vue 2 -->
<script>
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}
</script>
1
2
3
4
5
6
7
8
9
10

Или так, если предпочитаете использовать <template> в однофайловых компонентах:

<!-- Пример функционального компонента во Vue 2 с <template> -->
<template functional>
  <component
    :is="`h${props.level}`"
    v-bind="attrs"
    v-on="listeners"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Синтаксис в 3.x

# Компоненты создаются функциями

Теперь во Vue 3 все функциональные компоненты создаются с помощью простых функций. Другими словами, нет необходимости указывать опцию { functional: true } компонента.

Функции получают два аргумента: props и context. Аргумент context — объект, в котором содержатся свойства компонента attrs, slots и emit.

Кроме того, вместо неявной передачи h в функцию render, теперь h импортируется глобально.

Приведённый выше пример компонента <dynamic-heading> теперь можно переписать так:

import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading
1
2
3
4
5
6
7
8
9

# Однофайловые компоненты (SFC)

В версиях 3.x разница производительности между функциональными компонентами и компонентами с состоянием была кардинально уменьшена и теперь будет незначительной в большинстве случаев использования. В результате, стратегия миграции для разработчиков, использующих functional в однофайловых компонентах будет заключаться в удалении этого атрибута и переименовании всех ссылок props в $props и attrs в $attrs.

Используя компонент <dynamic-heading> из примера выше, в итоге он будет выглядеть так:

 

 
 









<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12

Ключевые отличия в том, что:

  1. Из <template> удалён атрибут functional
  2. Теперь listeners передаются как часть $attrs и могут быть удалены

# Дальнейшие шаги

Более подробную информацию об использовании новых функциональных компонентов, а также изменениях, вносимых в render-функции можно прочитать здесь: