Skip to content

注意

vueuse真的有好多超级好用的函数(设备位置和方向变化速度、捕获用户屏幕、窗口或浏览器标签页的内容等等等,超级超级多好用的函数),这里只记录的自己实际用过的

useRefHistory

跟踪响应式数据的更改(跟踪ref所做的每个更改存储到数组中,可以撤销和重做)

vue
<script setup>
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const counter = ref(0)
const { history, undo, redo } = useRefHistory(counter)
</script>

<template>
    <div class="flex items-center">
        <el-button @click="counter++">+</el-button>
        <h2 class="mx-4">{{ counter }}</h2>
        <el-button @click="counter--">-</el-button>
        <el-button @click="undo">撤销</el-button>
        <el-button @click="redo">重做</el-button>
    </div>
    <div class="flex flex-col">
        <div v-for="(item, index) in history" :key="index">
            {{ item }}
        </div>
    </div>
</template>

onClickOutside

监听元素外部的点击

vue
<script setup>
import { ref, useTemplateRef } from 'vue'
import { onClickOutside } from '@vueuse/core'
import { vOnClickOutside } from '@vueuse/components'

const visible = ref(false)
const modalRef = useTemplateRef('modalRef')

onClickOutside(modalRef, (event) => {
    console.log(event)
    console.log('点击了dialog外层')
    visible.value = false
})
function openDialog() {
    visible.value = true
}
function closeDialog() {
    console.log('指令形式')
    visible.value = false
}
</script>

<template>
    <el-button type="primary" @click="openDialog">open dialog</el-button>

    <div class="w-100 h-40 bg-coolGray" v-if="visible" ref="modalRef" v-on-click-outside="closeDialog">我是dialog</div>
</template>

useBattery

获取和监控设备的电池状态

  • charging: 是否正在充电
  • chargingTime: 剩余的充电时间
  • dischargingTime: 剩余的使用时间
  • level: 电池电量百分比

useFps

监控和调整应用程序的帧率

vue
<script setup>
import { useFps } from '@vueuse/core'

const fps = useFps()
</script>

useGeolocation

获取用户的地理位置(需要授权)

vue
<script setup>
import { useGeolocation } from '@vueuse/core'

const { coords, locatedAt, error, resume, pause } = useGeolocation()
</script>
  • coords: 当前位置信息(经纬度、海拔、精度、方向、速度)
  • locatedAt最后一次定位时间
  • error: 定位失败错误对象
  • resume: 恢复定位
  • pause: 暂停定位

useInfiniteScroll

监听元素是否滚动到底部(可监听任意元素)

vue
<script setup>
import { ref, useTemplateRef } from 'vue'
import { useInfiniteScroll } from '@vueuse/core'

const el = useTemplateRef('el')
const data = ref([])

const { reset } = useInfiniteScroll(
    el,
    () => {
        const length = data.value.length + 1
        data.value.push(...Array.from({ length: 5 }, (_, i) => length + i))
    },
    { distance: 10 }
)

function resetList() {
    data.value = []
    reset()
}
</script>

<template>
    <div ref="el" class="flex flex-col gap-2 p-4 w-300px h-300px m-auto overflow-y-scroll bg-gray-500/5 rounded">
        <div v-for="item in data" :key="item" class="h-15 bg-gray-500/5 rounded p-3">
            {{ item }}
        </div>
    </div>
    <button @click="resetList()">Reset</button>
</template>

useMouse

获取鼠标位置

ts
import { useMouse } from '@vueuse/core'

const { x, y, sourceType } = useMouse()

useDraggable

拖动元素

vue
<script setup>
import { useTemplateRef } from 'vue'
import { useDraggable } from '@vueuse/core'

const el = useTemplateRef('el')
const { x, y, style } = useDraggable(el, {
    initialValue: { x: 80, y: 80 },
    preventDefault: true
})
</script>

<template>
    <div
        ref="el"
        p="x-4 y-2"
        border="~ gray-800/30 rounded"
        shadow="~ hover:lg"
        class="fixed bg-blueGray cursor-move"
        style="touch-action: none"
        :style="style"
    >
        拖拽
        <div class="text-sm opacity-50">I am at {{ Math.round(x) }}, {{ Math.round(y) }}</div>
    </div>
</template>

useInterval

创建一个定时器,在指定的时间间隔内重复执行一个函数

vue
<script setup>
import { useInterval } from '@vueuse/core'

const counter = useInterval(200)
</script>

<template>
    <div>
        <p>{{ counter }}</p>
    </div>
</template>

useBase64

将文本、缓冲区、文件、画布、对象、映射、集和、图片转base64

ts
import { useBase64 } from '@vueuse/core'
import { Ref, ref } from 'vue'

const text = ref('')

const { base64 } = useBase64(text)

useDebounceFn

防抖

js
<script setup>
import { ref } from "vue";
import { useDebounceFn } from "@vueuse/core";

const query = ref("");
const result = ref("");

const search = (query) => {
  // 模拟搜索操作
  result.value = `搜索结果为: ${query}`;
};

// 使用 useDebounceFn 创建防抖函数
const onInput = useDebounceFn((event) => {
  search(event.target.value);
}, 500); // 500 毫秒的防抖时间
</script>

<template>
  <div>
    <input v-model="query" @input="onInput" placeholder="输入搜索内容..." />
    <p>搜索结果: {{ result }}</p>
  </div>
</template>

useThrottleFn

节流

vue
<script setup lang="ts">
import { useThrottleFn } from '@vueuse/core'
import { ref } from 'vue'

const updated = ref(0)
const clicked = ref(0)
const throttledFn = useThrottleFn(() => {
    updated.value += 1
}, 1000)

function clickedFn() {
    clicked.value += 1
    throttledFn()
}
</script>

<template>
    <div>
        <button @click="clickedFn">click</button>
        <p>{{ clicked }}</p>
        <p>{{ updated }}</p>
    </div>
</template>

useClipboard

复制文本到剪贴板

vue
<script setup>
import { useClipboard } from '@vueuse/core'
import { ref } from 'vue'

const input = ref('')

const { text, isSupported, copy } = useClipboard()
</script>

<template>
    <div v-if="isSupported">
        <p>
            剪切板: <code>{{ text }}</code>
        </p>
        <input v-model="input" type="text" />
        <button @click="copy(input)">复制</button>
    </div>
</template>

useFileDialog

选择文件

vue
<script setup>
import { useFileDialog } from '@vueuse/core'

const { files, open, reset, onCancel, onChange } = useFileDialog()

onChange((files) => {
    console.log('🚀 ~ onChange ~ files:', files)
})

onCancel(() => {})
</script>

<template>
    <button type="button" @click="open">选择文件</button>
</template>

useFullscreen

全屏

vue
<script setup>
import { useFullscreen } from '@vueuse/core'
import { useTemplateRef } from 'vue'

const el = useTemplateRef('el')
const { toggle } = useFullscreen(el)
</script>

<template>
    <div class="text-center">
        <div class="size-100 bg-amber" ref="el"></div>
        <button @click="toggle">全屏</button>
    </div>
</template>