Продолжая разбирать тему повторного (начало в статье Повторное использование кода Vue.js) использования кода Vue.js, я пришел к Composition API, который является основным новшеством Vue 3. Его также можно использовать во 2 версии Vue, если установить как отдельный пакет. В сети эти изменения вызвали бурное обсуждение, зачастую негодование, среди тех, кто пользуется данным фреймворком и создал не мало кода на старом API (Options API). Давайте разберемся почему появился новый API, как его использовать и в чем его плюсы.
Как я показал ранее в Vue для повторного использования кода существуют mixin-ы (и опция extends, которая работает так же). Но если вы использовали их ранее, то должны были заметить некоторые проблемы с ними связанные. А именно можно выделить такие вещи, как
- коллизии имен методов и свойств
- неявные зависимости
Коллизиями имен – существование в 2 или более mixin-ах свойств и методов с одинаковыми именами. Когда происходит такое, то один метод просто заменяет другой следуя политике слияния (которые можно переопределять, но это не очень удобно и читаемо).
Неявные зависимости – это, например, использование в методах mixin-а свойств, которые не объявлены в нем самом, а присутствуют, скажем, в компоненте, использующем этот mixin. При внесении изменений надо или помнить или смотреть откуда появляется данная переменная.
Это проблемы делают код менее читаемым и предсказуемым. И это становится еще большей проблемой, когда мы используем не только свои, но и mixin-ы из сторонних пакетов.
Новый Composition API решает эти проблемы. В предыдущей статье был компонент Mix.vue, где использовались mixin-ы, которые в своих методах оперируют свойством компонента. Я реализовал это через новый API, объясняю код и показываю как решились 2 проблемы, описанные выше.
<template>
<div class="component-border pl-1 mb-1 ms-1">
<h1>
Example Composition API
</h1>
<div>
<p>Count: {{ count }}</p>
<p>
<button
v-for="(action, index) in actions"
v-bind:key="index"
@click="action.handler"
class="me-1">
{{ action.text }}
</button>
</p>
</div>
</div>
</template>
<script>
import { ref } from '@vue/composition-api';
import useIncrement from "../briks/useIncrement";
import useDecrement from "../briks/useDecrement";
export default {
setup: () => {
const count = ref(0);
const { increment } = useIncrement(count);
const { decrement } = useDecrement(count);
function clear() {
count.value = 0;
}
const actions = ref([
{ text: 'Increment', handler: increment },
{ text: 'Decrement', handler: decrement },
{ text: 'Clear', handler: clear },
]);
return {
actions,
count,
increment,
clear,
decrement
}
},
};
</script>
const count = ref(0);
– это объявление реактивного свойства в Composition API. А clear()
– метод компонента, который устанавливает это свойство в 0. При этом приходится обращаться к величине через синтаксис count.value
. В шаблоне, однако это не требуется. actions – тоже реактивное свойство.
Но самое интересное, это – использование методов, которые добавлены в компонент из отдельных файлов:
import useIncrement from "../briks/useIncrement";
import useDecrement from "../briks/useDecrement";
...
const { increment } = useIncrement(count);
const { decrement } = useDecrement(count);
Это и есть замена миксинов. И здесь, чтобы зависимость стала явной, свойство count передано как параметр в обе функции.
export default function(count) {
function increment() {
count.value++;
}
return {
increment,
}
}
Таким образом решена проблема неявных зависимостей. Все зависимости становятся явными. По коду видно, что это внешняя величина.
При подключении методов в компонент мы можем задать задать им произвольные имена (смотрите в фигурных скобках).
const { increment } = useIncrement(count);
const { decrement } = useDecrement(count);
Правда в данном случае имена остались теми же, но вы вольны изменить это. Например, изменить имена на inc и dec, используя возможности деструктурирующего присваивания:
const { increment: inc } = useIncrement(count);
const { decrement: dec } = useDecrement(count);
И в конечном итоге все, что будет использоваться в шаблоне нужно вернуть
return {
actions,
count,
increment,
clear,
decrement
}
Здесь снова видим подход, при котором все делается явно.
Как мы видим обе проблемы прекрасно решены в новом Composition API.
Примеси в старом Options API позволяли получить нечто вроде наследования (на самом деле они мне напоминаю traits в php), в то время как в новом Composition API мы получает композицию. В различной литературе по архитектуре программ можно часто встретить фразу: “Предпочитайте композицию наследованию“. Теперь во Vue.js больше возможности следовать этой рекомендации.
Vue.js снова становится лучше. Вот цитата пользователя с habr:
Хмм… это только мне кажется, или у Vue и React такое развитие, что сначала в React сделают крутую фичу, а потом Vue сделают себе то же, но намного круче, как на примере с хуками/Composition API?
А что вы об этом думаете? Пишите в комментариях ваши ценные мысли.
PS. Конечно возможности нового API шире. Чтобы углубить знания придется обратиться к документации. А после этого нужную функцию можно искать в шпаргалке.
Код примеров – в моем репозитории
Использованные материалы:
- How the Vue Composition API Replaces Vue Mixins
- Документация Vue.js – Примеси
- Интересные новинки Vue 3
В продолжение темы. Возможно, вам будут интересны следующие мои статьи: