onClickOutside
监听元素外部的点击。对于模式或下拉菜单很有用。
常见于点击弹窗蒙层关闭,点击元素外部触发事件。
用法:
<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'
const target = ref(null)
onClickOutside(target, event => console.log(event))
</script>
<template>
<div ref="target">
Hello world
</div>
<div>Outside element</div>
</template>
onKeyStroke
可以监听键盘按下指定键的事件。
import { onKeyStroke } from '@vueuse/core'
onKeyStroke('ArrowDown', (e) => {
e.preventDefault()
})
聆听多个键
import { onKeyStroke } from '@vueuse/core'
onKeyStroke(['s', 'S', 'ArrowDown'], (e) => {
e.preventDefault()
})
// listen to all keys by [true / skip the keyDefine]
onKeyStroke(true, (e) => {
e.preventDefault()
})
onKeyStroke((e) => {
e.preventDefault()
})
自定义事件目标
onKeyStroke('A', (e) => {
console.log('Key A pressed on document')
}, { target: document })
忽略重复事件
import { onKeyStroke } from '@vueuse/core'
// use `autoRepeat` option
onKeyStroke('A', (e) => {
console.log('Key A pressed')
}, { dedupe: true })
自定义键盘事件
onKeyStroke('Shift', (e) => {
console.log('Shift key up')
}, { eventName: 'keyup' })
//或
onKeyUp('Shift', () => console.log('Shift key up'))
useElementHover
元素是否处于hover状态(反应性元素的悬停状态)。
在hover时展示不同的文字状态等可以用到
<script setup lang="ts">
import { ref } from 'vue'
import { useElementHover } from '@vueuse/core'
const el = ref<HTMLButtonElement>()
const isHovered = useElementHover(el, { delayEnter: 200, delayLeave: 600 })
</script>
<template>
<button ref="el">
<span>{{ isHovered ? 'Thank you!' : 'Hover me' }}</span>
</button>
</template>
useIdle
跟踪用户是否处于非活动状态。
在鼠标键盘不动的情况下,即处于非活动状态。
import { useIdle } from '@vueuse/core'
// 空闲时间达到5min后,idle.value为true
const { idle, lastActive } = useIdle(5 * 60 * 1000)
console.log(idle.value) // true or false
import { watch } from 'vue'
import { useCounter, useIdle } from '@vueuse/core'
const { inc, count } = useCounter()
const { idle, lastActive, reset } = useIdle(5 * 60 * 1000) // 5 min
watch(idle, (idleValue) => {
if (idleValue) {
inc()
console.log(`Triggered ${count.value} times`)
reset() // restarts the idle timer. Does not change lastActive value
}
})
组件使用
<template>
<UseIdle v-slot="{ idle }" :timeout="5 * 60 * 1000">
Is Idle: {{ idle }}
</UseIdle>
</template>
useMouse
反应性鼠标位置,用于获取鼠标x/y坐标和sourceType(mouse|touch)
import { useMouse } from '@vueuse/core'
const { x, y, sourceType } = useMouse()
默认情况下启用触摸。要仅检测鼠标更改,请将 touch
设置为 false
。dragover
事件用于在拖动时跟踪鼠标位置。
const { x, y } = useMouse({ touch: false })
定制提取器
还可以提供自定义提取器函数来从事件中获取位置。
import type { UseMouseEventExtractor } from '@vueuse/core'
import { useMouse, useParentElement } from '@vueuse/core'
const parentEl = useParentElement()
const extractor: UseMouseEventExtractor = event => (
event instanceof Touch
? null
: [event.offsetX, event.offsetY]
)
const { x, y, sourceType } = useMouse({ target: parentEl, type: extractor })
组件使用
<template>
<UseMouse v-slot="{ x, y }">
x: {{ x }}
y: {{ y }}
</UseMouse>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { stringify } from '@vueuse/docs-utils'
import { useMouse, useParentElement } from '@vueuse/core'
import type { UseMouseEventExtractor } from '@vueuse/core'
const parentEl = useParentElement()
const mouseDefault = reactive(useMouse())
const textDefault = stringify(mouseDefault)
const extractor: UseMouseEventExtractor = (event) => {
if (typeof Touch !== 'undefined' && event instanceof Touch)
return null
else
return [event.offsetX, event.offsetY]
}
const mouseWithExtractor = reactive(useMouse({ target: parentEl, type: extractor }))
const textWithExtractor = stringify(mouseWithExtractor)
</script>
<template>
<p>Basic Usage</p>
<pre lang="yaml">{{ textDefault }}</pre>
<p>Extractor Usage</p>
<pre lang="yaml">{{ textWithExtractor }}</pre>
</template>
usePointerSwipe
基于 PointerEvents 的反应式滑动检测, 鼠标拖动。
拖动元素时,触发回调事件
<script setup>
import { ref } from 'vue'
import { usePointerSwipe } from '@vueuse/core'
const el = ref(null)
const { isSwiping, direction } = usePointerSwipe(el)
</script>
<template>
<div ref="el">
Swipe here
</div>
</template>
const container = ref(null);
const { distanceX, isSwiping } = usePointerSwipe(container, {
onSwipe() {
console.log('onswipe');
},
onSwipeEnd() {
console.log('onend');
},
});
effect(() => {
console.log(isSwiping, distanceX);
});
<script setup lang="ts">
import { computed, ref } from 'vue'
import { usePointerSwipe } from '@vueuse/core'
import type { UseSwipeDirection } from '@vueuse/core'
const target = ref<HTMLElement | null>(null)
const container = ref<HTMLElement | null>(null)
const containerWidth = computed(() => container.value?.offsetWidth)
const left = ref('0')
const opacity = ref(1)
function reset() {
left.value = '0'
opacity.value = 1
}
const { distanceX, isSwiping } = usePointerSwipe(target, {
disableTextSelect: true,
onSwipe(e: PointerEvent) {
if (containerWidth.value) {
if (distanceX.value < 0) {
const distance = Math.abs(distanceX.value)
left.value = `${distance}px`
opacity.value = 1.25 - distance / containerWidth.value
}
else {
left.value = '0'
opacity.value = 1
}
}
},
onSwipeEnd(e: PointerEvent, direction: UseSwipeDirection) {
if (distanceX.value < 0 && containerWidth.value && (Math.abs(distanceX.value) / containerWidth.value) >= 0.5) {
left.value = '100%'
opacity.value = 0
}
else {
left.value = '0'
opacity.value = 1
}
},
})
</script>
<template>
<div ref="container" class="bg-gray-200 rounded relative w-full h-[80px] m-auto flex items-center justify-center overflow-hidden">
<button @click="reset">
Reset
</button>
<div
ref="target"
class="absolute w-full h-full top-0 left-0 bg-[#3eaf7c] flex items-center justify-center"
:class="{ 'transition-all duration-200 ease-linear': !isSwiping }"
:style="{ left, opacity }"
>
<p class="flex text-white items-center">
Swipe <mdi-arrow-right />
</p>
</div>
</div>
</template>
useScroll
反应式滚动位置和状态。
鼠标滚动信息。
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y, isScrolling, arrivedState, directions } = useScroll(el)
</script>
<template>
<div ref="el" />
</template>
带偏移量
const { x, y, isScrolling, arrivedState, directions } = useScroll(el, {
offset: { top: 30, bottom: 30, right: 30, left: 30 },
})
设置滚动位置
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el)
</script>
<template>
<div ref="el" />
<button @click="x += 10">
Scroll right 10px
</button>
<button @click="y += 10">
Scroll down 10px
</button>
</template>
平滑滚动
设置 behavior: smooth
以启用平滑滚动。behavior
选项默认为 auto
,这意味着不平滑滚动。有关详细信息,请参阅 window.scrollTo() 上的 behavior
选项。
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el, { behavior: 'smooth' })
// Or as a `ref`:
const smooth = ref(false)
const behavior = computed(() => smooth.value ? 'smooth' : 'auto')
const { x, y } = useScroll(el, { behavior })
指令用法
<script setup lang="ts">
import type { UseScrollReturn } from '@vueuse/core'
import { vScroll } from '@vueuse/components'
const data = ref([1, 2, 3, 4, 5, 6])
function onScroll(state: UseScrollReturn) {
console.log(state) // {x, y, isScrolling, arrivedState, directions}
}
</script>
<template>
<div v-scroll="onScroll">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
<!-- with options -->
<div v-scroll="[onScroll, { throttle: 10 }]">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
</template>
useScrollLock
锁定元素的滚动。
<script setup lang="ts">
import { useScrollLock } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const isLocked = useScrollLock(el)
isLocked.value = true // lock
isLocked.value = false // unlock
</script>
<template>
<div ref="el" />
</template>
指令用法
<script setup lang="ts">
import { vScrollLock } from '@vueuse/components'
const data = ref([1, 2, 3, 4, 5, 6])
const isLocked = ref(false)
const toggleLock = useToggle(isLocked)
</script>
<template>
<div v-scroll-lock="isLocked">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
<button @click="toggleLock()">
Toggle lock state
</button>
</template>
useSwipe
基于 TouchEvents 的反应式滑动检测(touch事件滚动)。
使用同usePointerSwipe,不同的是一个是pc端,一个是移动端的事件。
<script setup>
const el = ref(null)
const { isSwiping, direction } = useSwipe(el)
</script>
<template>
<div ref="el">
Swipe here
</div>
</template>
useTextSelection
基于 Window.getSelection 反应式跟踪用户文本选择。
文本选择相关数据
<script setup lang="ts">
import { useTextSelection } from '@vueuse/core'
const state = useTextSelection()
</script>
<template>
<p>{{ state.text }}</p>
</template>
文字内容,宽高,以及距离页面上下左右距离。
export declare function useTextSelection(
element?: MaybeRef<HTMLElement | Document | null | undefined>
): Ref<{
text: string
readonly height: number
readonly width: number
readonly left: number
readonly right: number
readonly top: number
readonly bottom: number
}>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useTextSelection } from '@vueuse/core'
const demo = ref()
const { rects, text } = useTextSelection()
const selectedStyle = computed(() => text.value ? 'text-primary' : 'text-gray-400')
</script>
<template>
<div ref="demo">
<p class="font-600 text-blue-600">
You can select any text on the page.
</p>
<p>
<strong>Selected Text:</strong>
<em
:class="selectedStyle"
class="whitespace-pre h-44 overflow-y-auto block"
>{{ text || 'No selected' }}</em>
</p>
<p>
<strong>Selected rects:</strong>
<pre class="h-72" lang="json">{{ rects }}</pre>
</p>
</div>
</template>