当前位置: 首页 > news >正文

vue自定义指令clickOutside篇、元素外部点击事件

文章目录

      • 前言
      • 代码解析 Vue3
      • 使用示例 Vue3
      • vue2 写法

前言

在前端开发中,我们常常会遇到需要检测用户是否点击了某个元素外部的场景,比如弹出框在用户点击外部时需要关闭。接下来我们来封装一个 clickOutside 自定义指令

代码解析 Vue3

import { Directive } from 'vue';

// 定义 ClickOutside 指令类型
const clickOutside: Directive<HTMLElement, () => void> = {
  // 当指令绑定到元素并插入到 DOM 中时调用
  mounted(el: HTMLElement, binding) {
    // 定义事件处理函数,类型注解表明它接收一个 MouseEvent 类型的参数
    const handler = (event: MouseEvent) => {
      // 判断点击的目标元素是否不在绑定指令的元素内部
      if (!el.contains(event.target as Node)) {
        // 调用绑定指令时传入的回调函数
        binding.value();
      }
    };
    // 给 document 添加 click 事件监听器
    document.addEventListener('click', handler);
    // 将事件处理函数存储在元素的自定义属性上,方便后续移除监听器
    el.__clickOutsideHandler = handler;
  },
  // 当指令所绑定的元素从 DOM 中移除时调用
  unmounted(el: HTMLElement) {
    // 移除之前添加到 document 上的 click 事件监听器
    document.removeEventListener('click', el.__clickOutsideHandler);
    // 删除元素上存储的事件处理函数属性
    delete el.__clickOutsideHandler;
  },
};

export default clickOutside;

使用示例 Vue3

<template>
  <div class="index">
    <div class="box">
      <div>举个例子</div>
      <div class="more" @click="moreClick">···</div>
      <div
        class="more-box"
        v-if="moreShow"
        v-click-outside="handleClickOutside"
      >
        <div>干嘛呢</div>
        <div>干嘛呢</div>
        <div>干嘛呢</div>
        <div>干嘛呢</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, Directive } from "vue";

const moreShow = ref(false);

function moreClick(event: any) {
  console.log("更多被戳了一下");
  moreShow.value = !moreShow.value;

  event.stopPropagation();
}

function handleClickOutside() {
  moreShow.value = false;
}
</script>

<style scoped lang="scss">
.index {
  overflow: hidden;
}

.box {
  width: 300px;
  height: 160px;
  border: 1px solid #00000055;
  border-radius: 10px;
  padding: 10px;
  margin: 100px;
  position: relative;
}

.more {
  cursor: pointer;
  text-align: center;
  width: 30px;
  height: 30px;
  position: absolute;
  top: 10px;
  right: 10px;
}

.more-box {
  position: absolute;
  right: -20px;
  width: 90px;
  border: 1px solid #00000055;
  border-radius: 10px;
  background: #ffffff;
  padding: 10px 0px;

  div {
    line-height: 36px;
    text-align: center;
  }
}
</style>

在这里插入图片描述

vue2 写法

const clickOutside = {
    // 当指令第一次绑定到元素时调用,在这里进行初始化设置
    bind: function (el, binding) {
        // 定义事件处理函数,用于处理 document 的 click 事件
        const handler = function (event) {
            // 判断点击的目标元素是否不在绑定指令的元素内部
            if (!el.contains(event.target)) {
                // 调用绑定指令时传入的回调函数
                binding.value();
            }
        };
        // 给 document 添加 click 事件监听器
        document.addEventListener('click', handler);
        // 将事件处理函数存储在元素的自定义属性上,方便后续移除监听器
        el.__clickOutsideHandler = handler;
    },
    // 当指令与元素解绑时调用,在这里进行清理工作
    unbind: function (el) {
        // 移除之前添加到 document 上的 click 事件监听器
        document.removeEventListener('click', el.__clickOutsideHandler);
        // 删除元素上存储的事件处理函数属性
        delete el.__clickOutsideHandler;
    }
};

export default clickOutside;

相关文章:

  • 拼多多面试题记录
  • JavaScript 中 多个 Promise 嵌套中,如何保证正确的执行顺序?
  • Python学习心得面向对象的三大特征
  • Linux应急响应-系统排查
  • 【清华大学】DeepSeek从入门到精通完整版pdf下载
  • web网络安全:SQL 注入攻击
  • AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践
  • 测试面试及实用功能解读
  • Jenkins 创建 Node 到 Windows
  • 【Java八股文】08-计算机网络面试篇
  • 【C++】面向对象的三大特性
  • 企业存储系统
  • windows环境下用docker搭建php开发环境dnmp
  • armv7l
  • 蓝桥杯学习大纲
  • 使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
  • 基于射频开关选择的VNA校准设计
  • vue3 背景虚化,文字高亮效果
  • git输错用户名或者密码
  • 连续学习、增量学习有哪些应用场景?
  • 网站建设优秀公司/进入百度
  • 高明网站建设公司/培训机构好还是学校好
  • 行业信息网站有哪些/销售找客户的方法
  • 区政府网站自查整改和制度建设/有什么软件可以推广
  • 怎样利用网站做推广/百度搜索次数统计
  • 哈尔滨网站制作方案/免费培训机构