VueUse – это коллекция утилит для Vue Composition API, которая содержит средства для взаимодействия с различными сенсорами, API состояния, анимацией и другими возможностями браузеров. Помимо этого, также, включает в себя ряд интеграций со сторонними популярными пакетами.
Содержание
С помощью VueUse можно быстро реализовать следующие функции: копирование в буффер обмена, бесконечная прокрутка, локальные резервные копии данных на случай плохого соединения, работа с горячими клавишами, обработка статуса батареи, работа с фокусом на элементах, работа с вибрацией устройства и еще многое другое.
Коллекция очень разносторонняя. В этой статье делается попытка создать небольшой обзор ее возможностей. Конечно, каждую утилиту не описать в одной статье. Здесь содержатся упоминания тех, которые заинтересовали при чтении документации.
Группы функций VueUse
В документации функции VueUse разбиты на группы (категории).
- State. Реактивная работа с данными в доступных браузеру хранилищах LocalStorage/SessionStorage. Манипуляции с историей значений реактивных элементов (ref)
- Elements. Взаимодействие с видимостью, размерами элементов, прокруткой, фокусом. Обработка перетаскивания и пересечения элементов.
- Browser. Работа с функциями браузера. Буфер обмена, темы оформления страниц, контрольные точки размера экрана, права доступа (Permissions API), Web Workers, FileSystemAccessAPI, предпочитаемые языки, Web Share API, Vibration API, Screen Orientation API, BroadcastChannel API и другое.
- Sensors. Использование Battery Status API, DeviceMotionEvent, DeviceOrientationEvent, Geolocation API, Network Information API, Pointer events, Web Speech API, TouchEvent, потоковых видео и звука, а также отслеживание выбранного текста и расширенная работа с клавиатурой и мышью.
- Network. Работа с EventSource или Server-Sent-Events для открытия постоянного соединения с HTTP-сервером. Взаимодействие с WebSocket и Fetch API.
- Animation. Использование Web Animations API и transitions для анимаций.
- Component, Watch, Reactivity. Ряд универсальных утилит разработки компонентов, для развитой работы с реактивностью и отслеживанием состояний.
- Array, Time. Работа в реактивном стиле с массивами и датами (временем).
- Utilities. Другие утилиты, которые не вошли в другие разделы.
Add-ons
Также ряд вещей оформлен как дополнительные модули.
- Electron – поддержка одноименной библиотеки для создания межплатформенных приложений.
- Firebase – работа с облачной платформой Firebase.
- Head – реактивное управлений секцией head через UnHead
- Integrations – интеграция с различными известными библиотеками. Например, axios, jwt-decode, qrcode, idb-keyval, async-validator, fuse (для нечеткого поиска), sortablejs и другими.
- Math – набор математических функций.
- Motion – предустановленный набор анимаций для элементов страницы с возможностью добавлять свои.
- Router – улучшения для работы с vue-router (обработка параметров адресной строки, переданных различными способами).
- RxJS – интеграция с одноименной библиотекой для создания асинхронных и событийно-ориентированных программ с использованием наблюдаемых последовательностей. Предоставляет один основной тип — Observable, вспомогательные типы (наблюдатель, планировщики, субъекты) и операторы, основанные на методах массива (map, filter, уменьшить, Every и т. д.), позволяющие обрабатывать асинхронные события как коллекции.
- SchemaOrg – работа с метаданными страницы для поисковых систем по одноименному стандарту.
- Sound – проигрывание звуковых файлов.
Некоторые возможности вблизи
Рассмотрим ряд утилит подробнее.
Создание хранилища через createGlobalState
Описать глобальное хранилище (наподобие Vuex) можно так:
// store.js
import { computed, ref } from 'vue'
import { createGlobalState } from '@vueuse/core'
export const useGlobalState = createGlobalState(
() => {
// state
const count = ref(0)
// getters
const doubleCount = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
return { count, doubleCount, increment }
}
)
Когда мы сделали так, то в другом месте приложения можно вызвать объявленную здесь функцию useGlobalState
и получить доступ к состоянию и функциях хранилища state = useGlobalState()
. Это будет работать примерно также как и Vuex.
Создание хранилища в localStorage или sessionStorage
Данные состояния при перезагрузке страницы не сохраняются. Но мы могли бы сделать так, чтобы они хранились. Например, использовать localStorage или sessionStorage. Разница между этими методами хранения в том, что localStorage сохраняет данные при закрытии браузера, а sessionStorage неизбежно их теряет при этом.
Сделать глобальное хранилище на базе localStorage можно таким способом:
<script setup lang="ts">
import { stringify } from '@vueuse/docs-utils'
import { createGlobalState, useStorage } from '@vueuse/core'
const useState = createGlobalState(() =>
useStorage('vue-use-locale-storage', {
name: 'Banana',
color: 'Yellow',
size: 'Medium',
}))
const state = useState()
const text = stringify(state)
</script>
<template>
<div>
<input v-model="state.name" type="text">
<input v-model="state.color" type="text">
<input v-model="state.size" type="text">
<pre lang="yaml">{{ text }}</pre>
</div>
</template>
Функция useStorage
принимает первым параметром имя ключа, под которым данные будут храниться в localStorage, а вторым – начальное значение.
Если мы хотим использовать sessionStorage, то нужно использовать третий параметр useState:
// bind string with SessionStorage, returns Ref<string>
const id = useStorage('my-id', 'some-string-id', sessionStorage)
Асинхронное реактивное состояние через useAsyncState
Когда какие-либо данные мы получаем с сервера и соединение не очень быстрое, то в ряде случаев, неплохим решением будет отображение предыдущего сохраненного значения. Рассмотрим следующий пример для useAsyncState из документации:
<script setup lang="ts">
import axios from 'axios'
import YAML from 'js-yaml'
import { useAsyncState } from '@vueuse/core'
const { isLoading, state, isReady, execute } = useAsyncState(
(args) => {
const id = args?.id || 1
return axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then(t => t.data)
},
{},
{
delay: 2000,
resetOnExecute: false,
},
)
</script>
<template>
<div>
<note>Ready: {{ isReady.toString() }}</note>
<note>Loading: {{ isLoading.toString() }}</note>
<pre lang="json" class="ml-2">{{ YAML.dump(state) }}</pre>
<button @click="execute(2000, { id: 2 })">
Execute
</button>
</div>
</template>
В useAsyncState первым аргументом передается промис, вторым – начальное значение, а третьим – опции. В данном случае используются опции delay (задержка в миллискундах перед выполнением прописа) и resetOnExecute (сброс или нет в начальное состояние перед выполнением промиса). В промисе описано получение данных с сервера.
Функция useAsyncState отдает ссылку на реактивную переменную с данными (state), индикаторы загрузки isLoading и isReady и функцию-действие execute(). Последняя функция позволяет выполнить промис снова с указанной задержкой (первый параметр) и новыми аргументами (второй параметр).
Итак, посмотрим как будет работать данный пример. Сначала будет работать указанная в опциях задержка в 2 секунды. На экране будет только Ready: false Loading: true {}
:
Затем начнет выполняться промис. Пока он не выполнился отображаться будет то же самое. А затем загрузятся и отобразятся данные:
Появились значения userId:1 id: 1
и другие данные, а индикаторы загрузки сменили значение Ready: true
.
Затем, если мы нажмем кнопку Execute, то будет вызвана функция execute, которая сначала выждет свою задержку (но она также указана величиной в 2 секунды) и выполнит промис передав новые аргументы { id: 2 }
. Пока промис не выполнился будут отображаться старые данные. Хотя в нашем шаблоне изменяется индикаторы загрузки на Ready: false Loading: true
. После загрузки вместе со сменой значений индикаторов мы увидим новые данные. Значение id = 2
и другое значение для title
:
Это похоже на работу библиотеки TanStack Query (Vue Query), описанной в предыдущей статье.
VueUse содержит очень много различных утилит решающих задачи в совершенно разных областях. Думаю, что любой разработчик может найти много полезных инструментов, если уделит некоторое время знакомству с возможностями этой библиотеки.
При чтении документации, правда, приходится много чего смотреть в исходном коде. Это по началу может мешать. Часто переключаться между документацией и исходным кодом не так удобно. Но скоро привыкаешь и начинаешь быстро находить нужные ответы.
Также существующая разбивка коллекции VueUse на группы функций кажется не всегда логичной и достаточной. Но, вероятно, со временем там будет больше порядка.
В целом присмотреться к этому набору инструментов не будет лишним. Будет интересно увидеть в комментариях какие из утилит VueUse используете вы и для чего.