Vue3封装点击按钮以外事件的两种实现方式

408 阅读1分钟

前言

最近用Vue3开发遇到一个场景,点击按钮以外区域时,触发对应事件。

Vue2中比较普遍的方法是封装自定义指令来实现,不过既然用Vue3了,就尝试一下它的新特性,用hooks的方式来实现。

方案一 自定义指令

<div
    class="show_remark"
    :class="[{ remarkType: remarkType }]"
    v-click-outside="onClickOutside"
>
    {{ remarkType ? "确认重置" : "重置" }}
</div>


// 定义按钮以外事件
const vClickOutside = {
  mounted(
    el,
    binding
  ) {
    function eventHandler(e) {
    // 如果点击的是按钮
      if (el.contains(e.target)) {
        remarkType.value = !remarkType.value;
        if (!remarkType.value) {
          inputText.value = "";
          clearAll();
        }
        return false;
      }
      
      // 点击的是按钮以外的区域
      // 如果绑定的参数是函数,正常情况也应该是函数执行
      if (binding.value && typeof binding.value === "function") {
        binding.value(e);
      }
    }
    
    // 用于销毁前注销事件监听
    el.__click_outside__ = eventHandler;
    
    // 添加事件监听
    document.addEventListener("click", eventHandler);
  },
  beforeUnmount(el) {
  
    // 移除事件监听
    document.removeEventListener("click", el.__click_outside__);
    
    // 删除无用属性
    delete el.__click_outside__;
  },
};

// 自定义指令参数,点击外部区域的处理函数,如关闭弹窗
const onClickOutside = () => {
  remarkType.value = false;
};

方案二 自定义hooks

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

// 把绑定的元素传进来
const useClickOutside = (elementRef:Ref<null | HTMLElement>) => {
    const isClickOutside = ref(false)
    
    const handler = (e: MouseEvent) => {
        if (elementRef.value) {
        //  判断点击的地方是否在元素以外
            if (elementRef.value.contains(e.target as HTMLElement)) {
                isClickOutside.value = false
            } else {
                isClickOutside.value = true
            }
        }
    }
    onMounted(() => {
      document.addEventListener("click", handler);
    });
    onUnmounted(() => {
      document.removeEventListener("click", handler);
    });
    return isClickOutside
}

export default useClickOutside

使用方法

const isClickOutside = useClickOutside(dropDownRef);

//通过watch来监听isClickOutside的变化
watch(isClickOutside, (newValue) => {
 // 。。。。。。
});

END

  • 希望这篇文章可以帮助到有需要的小伙伴们,有问题可以评论或私信我呀🤞🤞