VueUse 是 Vue 3 的必备库
对于那些不熟悉这个库的人,我建议你尝试一下,因为它实际上可以成为 Vue 3 项目中使用的标准,例如,曾经有适用于几乎所有 js 项目的 lodash 库。
其他人可能已经查看了它提供的所有广泛功能。有些人已经在 Vue 2 中使用过它,但并非所有新功能都支持旧版本。该库的功能令人印象深刻,有简单的实用程序,例如获取鼠标坐标,以及与 Firebase、Axios、Cookies、QR、本地存储、浏览器、RxJS、动画、地理位置、标准 Vue hooks 的扩展、媒体播放器等各种复杂的集成。尤雨溪本人是该库的赞助商之一,这似乎是个好兆头。该库会定期更新、修复错误,社区也在不断发展。所以,它具备成功的一切。
在本文中,我将仅讨论 4 个功能,当然,其他所有功能都需要关注。
onClickOutside
- 点击元素外部
我相信您可以自己完成库的安装,所以让我们直接进入有趣的功能。首先,我们来看一下一个简单的钩子,它可以跟踪给定元素外部的点击 - onClickOutside。许多软件包都提供此功能,几乎每个人都可能自己编写过该函数。通常,它是通过向所需元素添加自定义 Vue 指令来实现的,例如v-clickOutside
,但使用钩子的情况并不常见。
我在我的待办事项应用程序中使用了这个钩子,在组件中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 标签;如果您点击带有ref="todoItem"
属性的 li 标签之外的标签,则 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-components 中或在此文件中调用此函数(在我们的例子中是),我们将获得一个响应式笔记列表。notes 数组可以照常使用,记住,因为这是一个代理对象,并且列表本身存储在 notes.value 中。无需添加.value
到组件中的标记模板。
为了进行比较,查看库作者提供的 useStorage 示例也很有帮助。区别在于,在设置中,您不需要直接使用响应式存储,而是通过其 value 属性。在 html 模板中,一切照常。
useRefHistory
- 变化历史
useRefHistory
是一个钩子,用于记录数据更改的历史记录并提供撤消/重做功能。我用它在笔记编辑页面上创建了撤消和重做按钮。首先,我使用 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
和属性挂在按钮的 disabled 属性上。——需要在编辑完记录后清除历史记录。该钩子的作用几乎相同,但仅在调用命令时才会保存到历史记录。canUndo
canRedo
clear
canUndo
canRedo
clear
useManualRefHistory
commit()
结论
以上只是 VueUse 工具库中用于 Vue 3 开发的 4 个函数。想要更深入地学习,我建议你访问这个优秀的库的官网。虽然文档还有改进的空间,但库本身和文档都会定期更新。
我测试这个库的多边形的完整代码可以在这里查看。