vueUse 是 Anthony Fu 的一个开源项目, 它为 Vue 开发人员提供了大量适用于 Vue 2 和 Vue 3 的基本 Composition API 实用程序函数.
它有几十个解决方案, 适用于常见的开发者用例, 如跟踪 Ref 变化, 检测元素可见性, 简化常见的 Vue 模式, 键盘 / 鼠标输入等. 这是一个真正节省开发时间的好方法, 因为你不必自己添加所有这些标准功能.
我喜欢 VueUse 库, 因为它在决定提供哪些实用工具时真正把开发者放在第一位, 而且它是一个维护良好的库, 因为它与 Vue 的当前版本保持同步.
VueUse 有哪些实用程序?
如果你想看到每一个实用程序的完整列表, 我绝对建议你去看看官方文档[1]. 但总结一下, VueUse 中有 9 种类型的函数.
Animation-- 包含易于使用的过渡, 超时和计时功能.
Browser-- 可用于不同的屏幕控制, 剪贴板, 偏好等.
Component-- 提供了不同组件方法的简写.
Formatters-- 提供响应时间格式化功能.
Sensors-- 用来监听不同的 DOM 事件, 输入事件和网络事件.
State-- 管理用户状态(全局, 本地存储, 会话存储).
Utility-- 不同的实用函数, 如 getter, 条件, 引用同步等.
Watch-- 更多高级类型的观察器, 如可暂停的观察器, 退避的观察器和条件观察器.
Misc-- 不同类型的事件, webSockets 和 Web workers 的功能
这些类别中的大多数都包含几个不同的功能, 所以 VueUse 对于你的使用情况来说是很灵活的, 可以作为一个很好的地方来快速开始构建 Vue 应用程序.
在本教程中, 我们将看一下 5 个不同的 VueUse 函数, 这样你就可以了解在这个库中工作是多么容易.
但首先, 让我们将其添加到 Vue 项目中!
将 VueUse 安装到你的 Vue 项目中
VueUse 的最大特点之一是, 它只用一个软件包就能同时兼容 Vue 2 和 Vue 3!
安装 VueUse 有两种选择 NPM 或 CDN
NPM i @vueuse/core # yarn add @vueuse/core
我建议使用 NPM, 因为它使用法更容易理解, 但如果我们使用 CDN,VueUse 将在应用程序中通过 Windows.VueUse 访问.
对于 NPM 的安装, 所有的功能都可以通过使用标准的对象重构从 @vueuse/core 中导入, 像这样访问.
import { useRefHistory } from '@vueuse/core'
好了, 现在我们已经安装了 VueUse, 让我们在应用程序中使用它!
useRefHistory 跟踪响应式数据的更改
useRefHistory 跟踪对 Ref 所做的每一个改变, 并将其存储在一个数组中. 这使我们能够轻松地为我们的应用程序提供撤销和重做功能.
让我们看一个示例, 其中我们正在构建一个我们希望能够撤消的文本区域.
第一步是在不使用 VueUse 的情况下创建我们的基本组件 -- 使用 ref,textarea 和用于撤消和重做的按钮.
- Undo
- Redo
- import { ref } from 'vue'
- const text = ref('')
- button {
- border: none;
- outline: none;
- margin-right: 10px;
- background-color: #2ecc71;
- color: white;
- padding: 5px 10px;;
- }
然后, 让我们通过导入 useRefHistory 函数, 然后从我们的文本 ref 中提取 history,undo 和 redo 属性来添加 VueUse. 这就像调用 useRefHistory 并传递我们的 ref 一样简单.
- import {
- ref
- } from 'vue'
- import {
- useRefHistory
- } from '@vueuse/core'
- const text = ref('')
- const {
- history, undo, redo
- } = useRefHistory(text)
每次我们的 ref 更改时, 这都会触发一个观察者 -- 更新我们刚刚创建的 history 属性.
然后, 为了让我们能真正看到发生了什么, 让我们打印出模板内的历史记录, 同时在点击相应的按钮时调用我们的 undo 和 redo 函数.
- Undo
- Redo
- {{ entry }}
- import { ref } from 'vue'
- import { useRefHistory } from '@vueuse/core'
- const text = ref('')
- const { history, undo, redo } = useRefHistory(text)
- button {
- border: none;
- outline: none;
- margin-right: 10px;
- background-color: #2ecc71;
- color: white;
- padding: 5px 10px;;
- }
好的, 让我们运行它. 当我们输入时, 每个字符都会触发历史数组中的一个新条目, 如果我们点击 undo/redo, 我们会转到相应的条目.
还有不同的选项可以为此功能添加更多功能. 例如, 我们可以深入跟踪反应对象并限制这样的历史条目的数量.
- const { history, undo, redo } = useRefHistory(text, {
- deep: true,
- capacity: 10,
- })
有关完整的选项清单, 请务必查看文档.
onClickOutside 关闭模态
onClickOutside 检测在一个元素之外的任何点击. 根据我的经验, 这个功能最常见的使用情况是关闭任何模式或弹出窗口.
通常情况下, 我们希望我们的模态挡住网页的其他部分, 以吸引用户的注意力并限制错误. 然而, 如果他们真的点击了模态之外的内容, 我们希望它能够关闭.
只需两个步骤即可完成此操作:
为我们要检测的元素创建一个模板引用
使用此模板引用运行 onClickOutside
这是一个使用 onClickOutside 的带有弹出窗口的简单组件.
- Open Popup
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Corporis aliquid autem reiciendis eius accusamus sequi, ipsam corrupti vel laboriosam necessitatibus sit natus vero sint ullam! Omnis commodi eos accusantium illum?
- import { ref } from 'vue'
- import { onClickOutside } from '@vueuse/core'
- const open = ref(false) // state of our popup
- const popup = ref() // template ref
- // whenever our popup exists, and we click anything BUT it
- onClickOutside(popup, () => {
- open.value = false
- })
- button {
- border: none;
- outline: none;
- margin-right: 10px;
- background-color: #2ecc71;
- color: white;
- padding: 5px 10px;;
- }
- .popup {
- position: fixed;
- top: ;
- left: ;
- width: 100vw;
- height: 100vh;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(, , , 0.1);
- }
- .popup-content {
- min-width: 300px;
- padding: 20px;
- width: 30%;
- background: #fff;
- }
结果是这样的, 我们可以用我们的按钮打开弹出窗口, 然后在弹出内容窗口外点击关闭它.
useVModel 简化了 v-model 绑定
Vue 开发人员的一个常见用例是为组件创建自定义 v-model 绑定. 这意味着我们的组件接受一个值作为 prop, 并且每当该值被修改时, 我们的组件都会向父级发出更新事件.
useVModel 函数将其简化为只使用标准的 ref 语法. 假设我们有一个自定义的文本输入, 试图为其文本输入的值创建一个 v-model. 通常情况下, 我们必须接受一个值的 prop, 然后 emit 一个变化事件来更新父组件中的数据值.
我们可以使用 useVModel, 把它当作一个普通的 ref, 而不是使用 ref 并调用 props.value 和 update:value. 这有助于减少我们需要记住的不同语法的数量!
- type="text"
- :value="data"
- @input="update"
- />
- import { useVModel } from '@vueuse/core'
- export default {
- props: ['data'],
- setup(props, { emit }) {
- const data = useVModel(props, 'data', emit)
- console.log(data.value) // equal to props.data
- data.value = 'name' // equal to emit('update:data', 'name')
- const update = (event) => {
- data.value = event.target.value
- }
- return {
- data,
- update
- }
- },
- }
每当我们需要访问我们的值时, 我们只需调用 .value,useVModel 将从我们的组件 props 中给我们提供值. 而每当我们改变对象的值时, useVModel 会向父组件发出一个更新事件.
下面是一个快速的例子, 说明该父级组件可能是什么样子...
- {{ data }}
- :data="data"
- @update:data="data = $event"
- />
- import CustomInput from './components/CustomInput.vue'
- import { ref } from 'vue'
- export default {
- components: {
- CustomInput,
- },
- setup () {
- const data = ref('hello')
- return {
- data
- }
- }
- }
结果看起来像这样, 我们在父级中的值始终与子级中的输入保持同步.
使用 IntersectionObserver 跟踪元素可见性
在确定两个元素是否重叠时, Intersection Observers [2] 非常强大. 一个很好的用例是检查元素当前是否在视口中可见.
本质上, 它检查目标元素与根元素 / 文档相交的百分比. 如果该百分比超过某个阈值, 它会调用一个回调来确定目标元素是否可见.
useIntersectionObserver 提供了一个简单的语法来使用 IntersectionObserver API. 我们所需要做的就是为我们想要检查的元素提供一个模板 ref. 默认情况下, IntersectionObserver 将以文档的视口为根基, 阈值为 0.1-- 所以当这个阈值在任何一个方向被越过时, 我们的交集观察器将被触发.
这个例子的代码可能是这样的: 我们有一个假的段落, 只是在我们的视口中占据了空间, 我们的目标元素, 然后是一个打印语句, 打印我们元素的可见性.
- Is target visible? {{ targetIsVisible }}
- Hello world
- import { ref } from 'vue'
- import { useIntersectionObserver } from '@vueuse/core'
- export default {
- setup() {
- const target = ref(null)
- const targetIsVisible = ref(false)
- const { stop } = useIntersectionObserver(
- target,
- ([{ isIntersecting }], observerElement) => {
- targetIsVisible.value = isIntersecting
- },
- )
- return {
- target,
- targetIsVisible,
- }
- },
- }
- .container {
- width: 80%;
- margin: auto;
- background-color: #fafafa;
- max-height: 300px;
- overflow: scroll;
- }
- .target {
- margin-top: 500px;
- background-color: #1abc9c;
- color: white;
- padding: 20px;
- }
当我们运行并滚动它时, 我们会看到它正确地更新了.
我们还可以为 Intersection Observer 指定更多选项, 例如更改其根元素, 边距 (用于计算交点的根边界框的偏移量) 和阈值级别.
- const { stop } = useIntersectionObserver(
- target,
- ([{ isIntersecting }], observerElement) => {
- targetIsVisible.value = isIntersecting
- },
- {
- // root, rootMargin, threshold, Windows
- // full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
- threshold: 0.5,
- }
- )
同样重要的是, 这个方法返回一个 stop 函数, 我们可以调用这个函数来停止观察交叉点. 如果我们只想追踪一个元素在屏幕上第一次可见的时候, 这就特别有用.
在这段代码中, 一旦 targetIsVisible 被设置为 true, 观察者就会停止, 即使我们滚动离开目标元素, 我们的值也会保持为 true.
- const { stop } = useIntersectionObserver(
- target,
- ([{ isIntersecting }], observerElement) => {
- targetIsVisible.value = isIntersecting
- if (isIntersecting) {
- stop()
- }
- },
- )
useTransition 在值之间过渡
useTransition 是整个 veuse 库中我最喜欢的函数之一. 它允许我们在一行内平滑地转换数值.
我们有一个存储为 ref 的数字源和一个将在不同数值之间缓和的输出. 例如, 假设我们想建立一个计数器
我们可以通过三个步骤来做到这一点:
创建我们的 count ref 并将其初始化为零
使用 useTransition 创建 output ref(设置持续时间和转换类型)
更改 count 的值
- import { ref } from 'vue'
- import { useTransition, TransitionPresets } from '@vueuse/core'
- const source = ref(0)
- const output = useTransition(source, {
- duration: 3000,
- transition: TransitionPresets.easeOutExpo,
- })
- source.value = 5000
然后, 在我们的模板中, 我们希望显示 output 的值, 因为它可以在不同值之间平滑过渡.
- Join over
- {{ Math.round(output) }}+
- Developers
- import { ref } from 'vue'
- import { useTransition, TransitionPresets } from '@vueuse/core'
- const source = ref()
- const output = useTransition(source, {
- duration: 3000,
- transition: TransitionPresets.easeOutExpo,
- })
- source.value = 5000
这就是结果!
我们还可以使用 useTransition 来过渡整个数字数组, 这在处理位置或颜色时很有用. 处理颜色的一个绝招是使用一个计算属性将 RGB 值格式化为正确的颜色语法.
- COLOR CHANGING
- import { ref, computed } from 'vue'
- import { useTransition, TransitionPresets } from '@vueuse/core'
- const source = ref([, , ])
- const output = useTransition(source, {
- duration: 3000,
- transition: TransitionPresets.easeOutExpo,
- })
- const color = computed(() => {
- const [r, g, b] = output.value
- return `rgb(${r}, ${g}, ${b})`
- })
- source.value = [255, , 255]
一些进一步定制的酷方法是使用任何内置的过渡预设或使用 CSS 缓动函数来定义我们自己的过渡.
最后的想法
这绝不是 VueUse 的完整指南, 这些只是我发现 VueUse 库中最有趣的许多函数.
我喜欢所有这些实用功能对加快开发速度的帮助, 因为它们中的每一个都是为了解决具体而又常见的用例.
我很想听听你是如何在自己的项目中实施 VueUse 的. 请在下面留下任何评论.
来源: http://developer.51cto.com/art/202107/674896.htm