Композаблы (composables) в Quasar основаны на концепции Composition API из Vue 3 и представляют собой функции, которые инкапсулируют реактивную логику, состояния и методы для многократного использования в различных компонентах. Они позволяют структурировать код модульно, улучшая читаемость и поддерживаемость проекта.
Композабл — это обычная функция, которая возвращает реактивные
объекты, вычисляемые свойства или методы. Обычно она помещается в папку
src/composables/ для логической организации.
// src/composables/useCounter.js
import { ref } from 'vue';
export function useCounter() {
const count = ref(0);
function increment() {
count.value++;
}
function decrement() {
count.value--;
}
return {
count,
increment,
decrement
};
}
Использование композабла в компоненте:
<template>
<div>
<p>Счетчик: {{ count }}</p>
<q-btn @click="increment" label="Увеличить" />
<q-btn @click="decrement" label="Уменьшить" />
</div>
</template>
<script setup>
import { useCounter } from 'src/composables/useCounter';
const { count, increment, decrement } = useCounter();
</script>
Композаблы позволяют хранить reactive state и
вычислять зависимости между значениями. Для сложной логики часто
используют комбинацию ref, reactive и
computed.
import { reactive, computed } from 'vue';
export function useTodoList() {
const state = reactive({
todos: [],
filter: 'all'
});
const filteredTodos = computed(() => {
if (state.filter === 'completed') {
return state.todos.filter(todo => todo.done);
} else if (state.filter === 'active') {
return state.todos.filter(todo => !todo.done);
}
return state.todos;
});
function addTodo(text) {
state.todos.push({ text, done: false });
}
function toggleTodo(index) {
state.todos[index].done = !state.todos[index].done;
}
return { state, filteredTodos, addTodo, toggleTodo };
}
Quasar предоставляет компоненты и утилиты, которые удобно
использовать внутри композаблов. Например, Notify для
уведомлений или Dialog для модальных окон. Это позволяет
создать полностью независимую бизнес-логику, не зависящую от конкретного
компонента.
import { Notify } from 'quasar';
import { ref } from 'vue';
export function useNotifications() {
const messages = ref([]);
function notifySuccess(msg) {
Notify.create({ message: msg, color: 'green', position: 'top' });
messages.value.push({ msg, type: 'success' });
}
function notifyError(msg) {
Notify.create({ message: msg, color: 'red', position: 'top' });
messages.value.push({ msg, type: 'error' });
}
return { messages, notifySuccess, notifyError };
}
Частой задачей является создание композаблов для асинхронных
операций, таких как запросы к серверу. Для этого можно использовать
axios или встроенные методы fetch и управлять
состоянием загрузки, ошибками и результатом.
import { ref } from 'vue';
import axios from 'axios';
export function useApi(url) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
async function fetchData() {
loading.value = true;
error.value = null;
try {
const response = await axios.get(url);
data.value = response.data;
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
return { data, loading, error, fetchData };
}
src/composables/ — каждая
логическая единица должна иметь отдельный файл или подкаталог.use помогает
сразу понять, что это композабл: useAuth,
useForm, useCart.Композаблы хорошо сочетаются с Pinia для глобального состояния. Можно создавать композаблы, которые инкапсулируют вызовы к Pinia-сторам, предоставляя удобный интерфейс:
import { useUserStore } from 'src/stores/user';
import { computed } from 'vue';
export function useUser() {
const userStore = useUserStore();
const isLoggedIn = computed(() => !!userStore.token);
const username = computed(() => userStore.name);
function login(credentials) {
return userStore.login(credentials);
}
function logout() {
userStore.logout();
}
return { isLoggedIn, username, login, logout };
}
Композаблы создают основу для модульного и масштабируемого кода в Quasar, позволяя строить сложные приложения с чистой архитектурой и легко управляемым состоянием.