作者:Matt Maribojoc 译者:前端小智 来源:medium
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
VueUse 是 Anthony Fu 大佬的一个开源项目,它为Vue的开发者提供了大量用于 Vue2 和Vue3 的基本 Composition API 实用工具函数。
它有几十个用于常见开发人员用例的解决方案,如跟踪ref
更改,检测元素可见性,简化常见Vue模式,键盘/鼠标输入等。 这是真正节省开发时间的好方法,因为我们不必自己亲手添加所有这些标准功能,拿来主义,用就对了(再次感谢大佬的付出)。
我喜欢VueUse库,因为它在决定提供哪些实用工具时真正把开发者放在第一位,而且它是一个维护良好的库,因为它与Vue的当前版本保持同步。
VueUse 有哪些实用方法?
如果你想看到每一个实用程序的完整列表,建议去看看官方文档。但总结一下,VueUse 中有9种类型的函数。
- Animation(动画) - 包含易于使用的过渡、超时和计时功能
- Browser (浏览器) - 可以用于不同的屏幕控件、剪贴板、首选项等等
- Component (组件) - 为不同的组件方法提供简写
- Sensors (传感器)- 用来监听不同的DOM事件、输入事件和网络事件
- State (状态) - 管理用户状态(全局,本地存储,会话存储)
- Utility (实用方法)--不同的实用方法,如
getters
、conditionals
、ref synchronization
等。 - Watch --更高级的观察器类型,如可暂停的观察器、放弃的观察器和条件观察器
- 其它 - 事件、WebSockets和 Web workers 的不同类型的功能
将 Vueuse 安装到 Vue 项目中
VueUse 的最大特点之一是,它只用一个包就能兼容 Vue2 和 Vue3!
安装VueUse有两种选择:npm
或 CDN
npm i @vueuse/core # yarn add @vueuse/core
代码语言:javascript复制<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>
推荐使用NPM,因为它更容易理解,但如果我们使用CDN, 可能通过 window.VueUse
来访问。
使用 npm,可以通过解构的方式来获得想要的方法:
代码语言:javascript复制import { useRefHistory } from '@vueuse/core'
useRefHistory 跟踪响应式数据的变化
useRefHistory
跟踪对 ref
所做的每一个改变,并将其存储在一个数组中。这样我们能够轻松为应用程序提供撤销和重做功能。
来看一个示例,在该示例中,我们做一个能够撤销的文本区域
第一步是在没有 VueUse 的情况下创建我们的基本组件--使用ref
、textarea
、以及用于撤销和重做的按钮。
<template>
<p>
<button> Undo </button>
<button> Redo </button>
</p>
<textarea v-model="text"/>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
<style scoped>
button {
border: none;
outline: none;
margin-right: 10px;
background-color: #2ecc71;
color: white;
padding: 5px 10px;;
}
</style>
接着,导入useRefHistory
,然后通过 useRefHistory
从 text
中提取history
、undo
和redo
属性。
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
每当我们的ref
发生变化,更新history
属性时,就会触发一个监听器。
为了看看底层做了什么,我们把 history
内容打印出来。并在单击相应按钮时调用 undo
和redo
函数。
<template>
<p>
<button @click="undo"> Undo </button>
<button @click="redo"> Redo </button>
</p>
<textarea v-model="text"/>
<ul>
<li v-for="entry in history" :key="entry.timestamp">
{{ entry }}
</li>
</ul>
</template>
<script setup>
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
</script>
<style scoped>
button {
border: none;
outline: none;
margin-right: 10px;
background-color: #2ecc71;
color: white;
padding: 5px 10px;;
}
</style>
直接,跑起来,效果如下:
还有不同的选项,为这个功能增加更多的功能。例如,我们可以深入追踪 reactive 对象,并像这样限制 history
记录的数量。
const { history, undo, redo } = useRefHistory(text, {
deep: true,
capacity: 10,
})
onClickOutside 关闭 modal
onClickOutside
检测在一个元素之外的任何点击。根据我的经验,这个功能最常见的使用情况是关闭任何模态或弹出窗口。
通常,我们希望我们的模态屏蔽网页的其余部分,以吸引用户的注意和限制错误。然而,如果他们确实点击了模态之外,我们希望它关闭。
要做到这一点,只有两个步骤。
- 为要检测的元素创建一个模板引用
- 使用这个模板
ref
运行onClickOutside
这是一个简单的组件,使用onClickOutside
弹出窗口。
<template>
<button @click="open = true"> Open Popup </button>
<div class="popup" v-if='open'>
<div class="popup-content" ref="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?
</div>
</div>
</template>
<script setup>
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
})
</script>
<style scoped>
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;
}
</style
结果是这样的,我们可以用我们的按钮打开弹出窗口,然后在弹出内容窗口外单击关闭它。
useVModel 简化 v-model 的绑定。
Vue开发者的一个常见用例是为一个组件创建一个自定义的v-model
绑定。这也要求我们的组件接受一个 value
作为 prop,每当这个 value
被修改,我们的组件就会向父类发出一个 update
事件。
useVModel
函数将其简化为只使用标准的ref
语法。假设我们有一个自定义的文本输入,试图为其文本输入的值创建一个v-model
。通常情况下,我们必须接受一个 value
的 prop,然后发出一个 change
事件来更新父组件中的数据值。
我们可以使用useVModel
,把它当作一个普通的ref
,而不是使用ref
并调用props.value
和update:value
。这有助于减少我们需要记住的不同语法的数量!
<template>
<div>
<input
type="text"
:value="data"
@input="update"
/>
</div>
</template>
<script>
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
}
},
}
</script>
每当需要访问value
时,我们只需调用.value
,useVModel
将从我们的组件 props 中给我们提供值。而每当改变对象的值时,useVModel
会向父组件发出一个更新事件。
下面是父组件的一个简单示例
代码语言:javascript复制<template>
<div>
<p> {{ data }} </p>
<custom-input
:data="data"
@update:data="data = $event"
/>
</div>
</template>
<script>
import CustomInput from './components/CustomInput.vue'
import { ref } from 'vue'
export default {
components: {
CustomInput,
},
setup () {
const data = ref('hello')
return {
data
}
}
}
运行结果如下,父方的值总是与子方的输入保持同步:
使用 intersectionobserver 跟踪元素的可见性
当确定两个元素是否重叠时,useIntersectionObserver
是非常强大的。这方面的一个很好的用例是检查一个元素在视口中是否当前可见。
基本上,它检查目标元素与根元素/文档相交的百分比。如果这个百分比超过了某个阈值,它就会调用一个回调,确定目标元素是否可见。
useIntersectionObserver
提供了一个简单的语法来使用IntersectionObserver API
。我们所需要做的就是为我们想要检查的元素提供一个模板ref
。
默认情况下,IntersectionObserver
将以文档的视口为根基,阈值为0.1
--所以当这个阈值在任何一个方向被越过时,我们的交集观察器将被触发。
示例:我们有一个假的段落,只是在我们的视口中占据了空间,目标元素,然后是一个打印语句,打印我们元素的可见性。
代码语言:javascript复制<template>
<p> Is target visible? {{ targetIsVisible }} </p>
<div class="container">
<div class="target" ref="target">
<h1>Hello world</h1>
</div>
</div>
</template>
<script>
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,
}
},
}
</script>
<style scoped>
.container {
width: 80%;
margin: auto;
background-color: #fafafa;
max-height: 300px;
overflow: scroll;
}
.target {
margin-top: 500px;
background-color: #1abc9c;
color: white;
padding: 20px;
}
</style>
运行后,对应的值会更新:
我们还可以为我们的 Intersection Observer 指定更多的选项,比如改变它的根元素、边距(计算交叉点时对根的边界框的偏移)和阈值水平。
代码语言:javascript复制const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
},
{
// root, rootMargin, threshold, window
// full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
threshold: 0.5,
}
)
同样重要的是,这个方法返回一个 stop
函数,我们可以调用这个函数来停止观察交叉点。如果我们只想追踪一个元素在屏幕上第一次可见的时候,这就特别有用。
在这段代码中,一旦targetIsVisible
被设置为true
,observer 就会停止,即使我们滚动离开目标元素,我们的值也会保持为 true
。
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
if (isIntersecting) {
stop()
}
},
)
使用 useTransition 做个数字加载动画
useTransition
是整个VueUse库中我最喜欢的函数之一。它允许我们只用一行就能顺利地在数值之间进行过渡。
如果使用 useTransition
做一个下面这样的效果,要怎么做呢?
我们可以通过三个步骤来做到这一点。
- 初始化一个
ref
变量count
,初始值为0
- 使用
useTransition
创建一个变量output
- 改变 count 的值
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const count = ref(0)
const output = useTransition(count , {
duration: 3000,
transition: TransitionPresets.easeOutExpo,
})
count.value = 5000
</script>
然后在 template 中显示 output
的值:
<template>
<h2>
<p> Join over </p>
<p> {{ Math.round(output) }} </p>
<p>Developers </p>
</h2>
</template>
<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const count = ref(0)
const output = useTransition(count, {
duration: 3000,
transition: TransitionPresets.easeOutExpo,
})
count.value = 5000
</script>
运行结果:
我们还可以使用useTransition
转换整个数字数组。 使用位置或颜色时,这非常有用。 使用颜色的一个很好的技巧是使用计算的属性将RGB
值格式化为正确的颜色语法。
<template>
<h2 :style="{ color: color } "> COLOR CHANGING </h2>
</template>
<script setup>
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]
</script>
总结
这不是VueUse的完整指南。这些只是我平常比较常用的函数,还有很多好用的函数,大家可以自行到官网去学习使用。
~完,我去刷碗了,周末不刷碗,晚上跪榴莲。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://learvue.co/2021/07/5-...
交流
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。