跳到主要内容

useMouse

2024年03月20日
柏拉文
越努力,越幸运

一、认识


useMouse() 是一个鼠标追踪器, 实现了鼠标追踪的功能

二、基础实现


2.1 定义

import { onMounted, onUnmounted, ref } from 'vue'

export function useMouse() {
const x = ref(0)
const y = ref(0)

function handle(e:any) {
x.value = e.pageX
y.value = e.pageY
}

onMounted(() => {
window.addEventListener('mousemove', handle)
})

onUnmounted(() => {
window.removeEventListener('mousemove', handle)
})

return { x, y }
}

2.2 调用

<template>
<div>
<div>x: {{ x }}</div>
<div>y: {{ y }}</div>
</div>
</template>

<script setup lang="ts">
import { useMouse } from './composables/useMouse'

const { x, y } = useMouse()
</script>

三、高阶实现


对于 useMouse 获取坐标如果多个组件使用则会添加多个监听,增加性能成本,这个时候使用EffectScope更友好, 这样无论多少组件使用,只会进行一次监听,不使用时同时清除监听

3.1 实现

import { effectScope, onScopeDispose, ref } from "vue";

function useMouse(){
const x = ref(0);
const y = ref(0);

const updateMouse = (e: MouseEvent) => {
x.value = e.pageX;
y.value = e.pageY;
}

window.addEventListener('mousemove', updateMouse);

onScopeDispose(()=>{
window.removeEventListener('mousemove', updateMouse);
});

return {x,y}
}

function createSharedComposable(composable){
let state;
let scope;
let subscribers = 0;

const dispose = ()=>{
if(scope && --subscribers <= 0){
scope.stop();
state = scope = null;
}
}

return (...args)=>{
subscribers++;
if(!state){
scope = effectScope(true);
state = scope.run(()=> composable(...args));
}
onScopeDispose(dispose);
return state;
}
}

const useShareMouse = createSharedComposable(useMouse);
export default useShareMouse;

3.2 调用

<template>
<div>
<div>x: {{ x }}</div>
<div>y: {{ y }}</div>
</div>
</template>

<script setup lang="ts">
import { useMouse } from './composables/useMouse'

const { x, y } = useMouse()
</script>