VueUse中的這五個函數,也太好用了吧
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
- <script src="https://unpkg.com/@vueuse/shared"></script>
- <script src="https://unpkg.com/@vueuse/core"></script>
推薦使用NPM,因為它更容易理解,但如果我們使用CDN, 可能通過 window.VueUse 來訪問。
使用 npm,可以通過解構的方式來獲得想要的方法:
- 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 會向父組件發出一個更新事件。
下面是父組件的一個簡單示例
- <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--所以當這個閾值在任何一個方向被越過時,我們的交集觀察器將被觸發。
示例:我們有一個假的段落,只是在我們的視口中占據了空間,目標元素,然后是一個打印語句,打印我們元素的可見性。
- <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 指定更多的選項,比如改變它的根元素、邊距(計算交叉點時對根的邊界框的偏移)和閾值水平。
- 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的完整指南。這些只是我平常比較常用的函數,還有很多好用的函數,大家可以自行到官網去學習使用。
作者:Matt Maribojoc 譯者:前端小智 來源:medium
原文:https://learvue.co/2021/07/5-vueuse-library-functions-that-can-speed-up-development/