От автора: тем, кто не знаком с библиотекой VueUse, советую познакомится с ней, так как она может де-факто стать стандартом для использования в проектах Vue 3, как, например, когда-то была библиотека lodash практически для любых js-проектов.
Многие, вероятно, уже ознакомились с различными функциями, которые она предоставляет. Некоторые уже использовали ее во Vue 2, но не все новые функции поддерживают старую версию. Арсенал библиотеки впечатляет, есть простые утилиты, такие как получение координат мыши, и различные сложные интеграции с Firebase, Axios, cookie, QR, локальным хранилищем, браузером, RxJS, анимацией, геолокацией, расширениям для стандартных хуков Vue, медиаплеером и многое другое. Сам Evan You отмечен среди спонсоров библиотеки, что, кажется, хороший знак. Библиотека регулярно получает обновления, исправления ошибок, ее сообщество растет. Так что все для успеха есть.
В этой статье я расскажу только о 4 функциях, но, конечно, все остальные также требуют внимания.
onClickOutside – клики вне элемента
Я уверен, что вы справитесь с установкой библиотеки самостоятельно, так что перейдем сразу к интересным функциям. Чтобы разогреться, рассмотрим простой хук, отслеживающий клики за пределами заданного элемента — onClickOutside. Есть много пакетов, которые предоставляют эту функцию. Обычно она реализуется, например, путем добавления пользовательской директивы Vue к желаемому элементу v-clickOutside, но использование хука необычно. Я использовал этот хук в своем приложении todo в компоненте ToDoItem.vue:
<template> <li ref="todoItem"> <input type="checkbox" /> <span v-if="!editable" @click="editable = !editable"> {{ todo.text ? todo.text : "Click to edit Todo" }} </span> <input v-else type="text" :value="todo.text" @keyup.enter="editable = !editable" /> </li> </template> <script lang="ts"> import { defineComponent, PropType, ref } from "vue" import ToDo from "@/models/ToDoModel" import { onClickOutside } from "@vueuse/core" export default defineComponent({ name: "TodoItem", props: { todo: { type: Object as PropType<ToDo>, required: true } }, setup() { const todoItem = ref(null) const editable = ref(false) onClickOutside(todoItem, () => { editable.value = false }) return { todoItem, editable } } }) </script>
Я удалил лишний код, чтобы не отвлекаться, но компонент все еще достаточно велик. Обратите внимание на код внутри настройки хука, сначала мы создаем пустую ссылку todoItem, которой мы присваиваем нужный элемент в шаблоне, а затем — передаем в хук onClickOutside первый параметр, а второй параметр — это обратный вызов с нужными действиями. Когда вы кликаете по тегу span, он будет заменен тегом input, а если вы кликнете вне тега li с атрибутом ref=»todoItem», то input будет заменен тегом span.
useStorage и createGlobalState- реактивное локальное хранилище
Следующая функция, о которой я расскажу, — это useStorage. Эта функция позволяет хранить данные в файлах Window.localStorage. Ее удобно использовать совместно с createGlobalState, которая используется для создания глобального хранилища. Теперь данные будут сохраняться, обновляться и удаляться автоматически и не исчезнут после перезагрузки страницы. Ниже приведен пример использования этих функций:
// @/store/index.ts import { createGlobalState, useStorage } from '@vueuse/core' import Note from '@/models/NoteModel' // state export const useGlobalNotes = createGlobalState( () => useStorage('my-notes', [] as Note[]), ) // actions const notes = useGlobalNotes() // for local use export const addNote = function (note) { notes.value.push(note) } export const deleteGlobalNote = function (noteId: number) { notes.value = notes.value.filter(note => note.id != noteId) }
Первый параметр функции useStorage принимает ключ, в которым будут сохраняться данные localStorage, а второй — начальное значение. createGlobalState создает функцию-оболочку для передачи состояния компонентам. Вызвав эту функцию (в нашем случае это useGlobalNotes()) в Vue-компонентах или прямо здесь, в этом файле, мы получим реактивный список заметок. Массив заметок можно использовать как обычно, помня, что, это только прокси-объект, а сам список хранится в notes.value. Не нужно добавлять .value в шаблоны разметки компонентов.
Для сравнения также полезно увидеть пример useStorage от авторов библиотеки. Разница в том, что при настройке вам нужно работать с реактивным хранилищем не напрямую, а через его свойство value. В шаблоне html все как обычно.
useRefHistory — история изменений
useRefHistory — это хук, который будет записывать историю изменений данных и обеспечивать функциональность undo/redo. Я использовал его для создания кнопок Undo и Redo на странице редактирования заметки. Сначала я создал переменную, используя ref. Давайте внимательнее посмотрим на код:
<!-- Note.vue --> <template> <!-- ... --> <div> <button type="button" @click="undo" :disabled="!canUndo">Undo</button> <button type="button" @click="redo" :disabled="!canRedo">Redo</button> </div> <!-- ... --> </template> <script lang="ts"> import { defineComponent } from "vue" import { useRefHistory } from "@vueuse/core" import ToDo from '@/models/ToDoModel' export default defineComponent({ setup() { const note = ref({ title: "", todos: [] as ToDo[] }) const { undo, redo, canUndo, canRedo, clear } = useRefHistory(note, { deep: true }) const updateTitle = (title: string) => { note.value.title = title } const addNewTodo = () => { note.value.todos.push({} as ToDo) } const onRemoveTodo = (index: number) => { note.value.todos.splice(index, 1) } return { note, addNewTodo, onRemoveTodo, updateTitle, undo, redo, canUndo, canRedo, clear } }, }) </script>
Мы создаем реактивную переменную, используя ref, передаем ее в useRefHistory, в параметрах хука указываем deep:true для вложенных объектов. Используя useRefHistory мы получаем history, undo, redo, canUndo, canRedo и clear. Свойства canUndo и canRedo висят на отключенных атрибутах кнопок. Clear — очистить историю после окончания редактирования записей. Хук useManualRefHistory делает почти то же самое, но сохранение истории происходит только тогда , когда вызывается команда commit().
Заключение
Я рассмотрел только 4 функции из большого арсенала инструментов VueUse для разработки Vue 3. Для более глубокого изучения советую посетить сайт этой замечательной библиотеки. Документация регулярно обновляется, как и сама библиотека.
Автор: Roman Harmyder
Источник: dev.to
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен