Компонент: скрипт Composition API
Composition API основан на принципе объявления реактивных переменных состояния и формировании логики из нескольких функций. Это более свободный способ написания логики компонента. Для его эффективного использования необходимо хорошо понимать принципы реактивности Vue. При этом гибкость подхода позволяет применять более мощные паттерны для организации и повторного использования логики между компонентами.
Разработчики, имеющие опыт с Options API, могут оценить его преимущество в упорядоченности кода внутри компонента. Тем не менее у Options API есть ограничения, которые проявляются при увеличении сложности компонента — особенно когда компонент решает сразу несколько логических задач.
Преимущества Composition API
Повторное использование логических элементов. Одно из ключевых преимуществ — возможность выносить логику компонента в составные функции — composables. Они устраняют недостатки, свойственные миксинам в Options API. Кроме того, вынесение повторяющегося кода в composables помогает следовать принципу чистого кода — DRY.
Более гибкая организация кода. Composition API даёт возможность структурировать код более удобным образом.
Ниже приведён пример организации кода одного и того же компонента с использованием Options API и Composition API:

Код, относящийся к одной логической задаче, теперь можно объединить в одном месте. Отпадает необходимость переключаться между различными блоками параметров при работе над конкретной логической задачей.
Улучшенная типизация. Composition API оперирует преимущественно обычными переменными и функциями, которые хорошо совместимы с типизацией. Код на Composition API лучше распознаётся IDE, которая подсказывает варианты при написании. Код на Composition API практически одинаково выглядит в TypeScript и в чистом JavaScript.
Оптимизированная сборка в продакшене. Composition API с использованием <script setup> обеспечивает более эффективную сборку проекта по сравнению с Options API. Это достигается за счёт того, что шаблон компонента работает в том же окружении, что и логическая часть. Шаблон может напрямую обращаться к переменным из блока логики без промежуточного проксирования через экземпляр компонента.
Реактивные данные
В Composition API реактивные переменные создаются с помощью функций ref и reactive.
ref
Функция ref позволяет объявить реактивные данные в компоненте Vue. В качестве аргумента передаётся начальное значение:
import { ref } from 'vue'
const myValue = ref(0)
myValue — это объект со свойством value, через которое осуществляется доступ к значению.
import { ref } from 'vue'
const myValue = ref(0)
console.log(myValue.value) // => 0
myValue.value = 3
console.log(myValue.value) // => 3
Функция ref создаёт реактивную ссылку на значение. Концепция ссылок широко используется в Composition API.
shallowRef
shallowRef — аналог ref, однако он не отслеживает изменения вложенных свойств объекта. Это бывает полезно, когда нужно реагировать только на замену корневого значения.
const state = shallowRef({ number: 1 })
// НЕ запустит обновление в компоненте
state.value.number = 2
// Запустит обновление в компоненте
state.value = { number: 2 }
reactive
reactive — ещё один способ объявления реактивных данных в Composition API. В отличие от ref, он инициализируется исключительно объектом, но при этом каждое свойство объекта становится отдельной реактивной переменной.
const data = reactive({
name: 'Иван Петров',
age: 23,
})
reactive не требует обращения через value, что делает код более лаконичным.
Отслеживание изменений
Для наблюдения за изменениями в Composition API используется функция watch. Она принимает два обязательных и один необязательный аргумент:
- Реактивная ссылка или функция, результат которой необходимо отслеживать.
- Функция-колбэк, вызываемая при каждом изменении наблюдаемого значения.
- Опциональные параметры.
Колбэк получает два аргумента: newValue и oldValue — новое и предыдущее значения наблюдаемой сущности.
Пример использования:
import { ref, watch } from 'vue'
const myValue = ref(0)
watch(myValue, (newValue, oldValue) => {
console.log("Значение изменено с " + oldValue + " на " + newValue)
})
При каждом изменении myValue в консоль будет выведено соответствующее сообщение. Например, при смене значения с 0 на 5 отобразится «Значение изменено с 0 на 5».
Вычисляемые свойства
По аналогии с ref и watch, вычисляемые свойства создаются при помощи функции computed.
Допустим, в предыдущем примере нам постоянно нужно значение myValue в квадрате. Это можно реализовать через отслеживание myValue:
import { ref, watch } from 'vue'
const myValue = ref(0)
const myValueSquare = ref(0)
watch(myValue, (newValue) => {
myValueSquare.value = newValue ** 2
})
Однако во Vue есть более элегантный способ:
import { computed, ref } from 'vue'
const myValue = ref(0) // => 0
const myValueSquare = computed(() => myValue.value ** 2) // => 0
myValue.value = 2
console.log(myValue.value) // => 2
console.log(myValueSquare.value) // => 4
Функция computed, как и ref, создаёт реактивную ссылку. Доступ к значению осуществляется через .value. Однако поле value по умолчанию доступно только для чтения.
Чтобы обеспечить запись в computed, необходимо задать свойства get и set.
import { computed, ref } from 'vue'
const myValue = ref(0)
const myValueSquare = computed({
get() {
return myValue.value ** 2
},
set(value) {
myValue.value = Math.sqrt(value)
}
})
myValue.value = 2
console.log(myValue.value) // => 2
console.log(myValueSquare.value) // => 4
myValueSquare.value = 9
console.log(myValue.value) // => 3
console.log(myValueSquare.value) // => 9
В приведённом коде геттер (поле get) остаётся прежним. Однако теперь допускается прямое присвоение значения myValueSquare:
myValueSquare.value = 9
При этом вызовется метод set, который запишет в myValue квадратный корень из 9, то есть 3. Соответственно, геттер вернёт записанное значение — 9.
Методы в Composition API
Для использования методов в Composition API не нужно придерживаться каких-либо специальных правил — методы представляют собой обычные JavaScript-функции.
Предположим, нам нужна функция, устанавливающая случайное значение. Реализация проста:
import { ref } from 'vue'
const myValue = ref(0)
const randomize = () => {
myValue.value = Math.random()
}
Здесь randomize выступает аналогом метода и точно так же доступна в шаблоне компонента.
<button @click="randomize">
Randomize
</button>
Ограничения Composition API
Внутри <script setup> нельзя использовать ключевое слово this, так как оно не ссылается на экземпляр компонента.
Представим компонент счётчика, написанный на Options API:
export default {
data() {
return {
myValue: 0
}
},
methods: {
increment() {
this.myValue = this.myValue + 1
}
}
}
В методе increment используется this.myValue, поскольку это свойство экземпляра компонента.
Однако при переписывании на Composition API такой подход приведёт к ошибке:
const myValue = ref(0)
function increment() {
this.myValue = this.myValue + 1 // => Получим ошибку Cannot read properties of undefined (reading 'myValue')
}
Необходимо заменить this.myValue = this.myValue + 1 на myValue.value = myValue.value + 1.