办学质量监测教学评价系统
shenrongliang
2025-06-13 11d86cc6c26bb4f709e407acadf4805c2024e79f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import type { Arrayable, MaybeElementRef } from '@vueuse/core';
 
import type { Ref } from 'vue';
 
import { computed, onUnmounted, ref, unref, watch } from 'vue';
 
import { isFunction } from '@vben/utils';
 
import { useElementHover } from '@vueuse/core';
 
/**
 * 监测鼠标是否在元素内部,如果在元素内部则返回 true,否则返回 false
 * @param refElement 所有需要检测的元素。如果提供了一个数组,那么鼠标在任何一个元素内部都会返回 true
 * @param delay 延迟更新状态的时间
 * @returns 返回一个数组,第一个元素是一个 ref,表示鼠标是否在元素内部,第二个元素是一个控制器,可以通过 enable 和 disable 方法来控制监听器的启用和禁用
 */
export function useHoverToggle(
  refElement: Arrayable<MaybeElementRef>,
  delay: (() => number) | number = 500,
) {
  const isHovers: Array<Ref<boolean>> = [];
  const value = ref(false);
  const timer = ref<ReturnType<typeof setTimeout> | undefined>();
  const refs = Array.isArray(refElement) ? refElement : [refElement];
  refs.forEach((refEle) => {
    const eleRef = computed(() => {
      const ele = unref(refEle);
      return ele instanceof Element ? ele : (ele?.$el as Element);
    });
    const isHover = useElementHover(eleRef);
    isHovers.push(isHover);
  });
  const isOutsideAll = computed(() => isHovers.every((v) => !v.value));
 
  function setValueDelay(val: boolean) {
    timer.value && clearTimeout(timer.value);
    timer.value = setTimeout(
      () => {
        value.value = val;
        timer.value = undefined;
      },
      isFunction(delay) ? delay() : delay,
    );
  }
 
  const watcher = watch(
    isOutsideAll,
    (val) => {
      setValueDelay(!val);
    },
    { immediate: true },
  );
 
  const controller = {
    enable() {
      watcher.resume();
    },
    disable() {
      watcher.pause();
    },
  };
 
  onUnmounted(() => {
    timer.value && clearTimeout(timer.value);
  });
 
  return [value, controller] as [typeof value, typeof controller];
}