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>