vue自定义指令封装-是否点击当前元素以外区域

elementui中有对应指令封装,直接引入使用即可(下面有使用示例),如果不想依赖组件库,可以使用一下简单版本

1. 版本环境

  • vue2
  • 工程化脚手架

2. v-clickoutside 指令代码

js 复制代码
// 点击外部的事件处理函数
function handleClickOutside(el, binding, e) {
    // 判断点击的目标元素 是否 在绑定指令的元素 内部
    if (el.contains(e.target)) return;
    // 如果指令绑定的值为 false(比如弹出元素还未加载) 直接不执行
    if (!binding.value || el.contains(e.target)) return;
    // 触发绑定的回调函数(binding.value 就是指令绑定的方法)
    if (typeof binding.value === "function") {
        binding.value(e);
    }
}

export default {
    // 指令绑定到元素时触发,只执行一次
    bind(el, binding) {
        // 把事件处理函数挂载到元素实例上 方便后续解绑
        // 避免多个指令实例共用一个函数导致冲突
        el.__vueClickOutside__ = (e) => handleClickOutside(el, binding, e);
        // 全局监听鼠标按下事件  mousedown 而非 click,响应更快无延迟 
        document.addEventListener("mousedown", el.__vueClickOutside__);
    },

    // 指令与元素解绑时触发 防止内存泄漏
    unbind(el) {
        // 移除全局事件监听
        document.removeEventListener("mousedown", el.__vueClickOutside__);
        // 删除元素上的自定义属性
        delete el.__vueClickOutside__;
    },
};

3. vu中 注册 指令

  • main.js vue项目入口文件
js 复制代码
import Vue from 'vue'
import App from './App.vue'

import clickoutside from '@/directives/clickoutside' // 替换为你的指令js文件所在目录

Vue.directive('clickoutside', clickoutside) // 注册指令



new Vue({
  render: h => h(App),
}).$mount('#app')

4. 页面/组件中使用

vue 复制代码
<template>
  <div>
  
  <button @click="showPopup=true">打开弹出层</button>
  
  <div class="popups" v-if="showPopup" v-clickoutside="showPopup && handleClose">
     弹出层内容
  </div>
  
  </div>


</template>

<script>

export default {

    data() {
        return {
            showPopup: false,
        }
    },
    
    methods:{
        handleClose() {
            this.showPopup = false
        },
    
    
    }


}


</script>

element ui的指令使用示例

  • vue3版本换成对应的语法 即可
vue 复制代码
<template>
    <!-- 给需要监听外部点击的容器绑定指令 -->
    <div class="custom-dropdown" v-clickoutside="closeMenu">
        <el-button @click="isOpen = !isOpen">展开菜单</el-button>
        <!-- 下拉内容 -->
        <div v-show="isOpen" class="menu">
            <p>菜单选项1</p>
            <p>菜单选项2</p>
        </div>
    </div>
</template>
<script>

 // import clickoutside from "element-ui/src/utils/clickoutside"; // 默认全局已注册,可单独引入

export default {

 //   directives: {
 //       clickoutside
 //   },
 
    data() {
        return {
            isOpen: false // 控制菜单显示
        }
    },
    methods: {
        // 点击外部区域触发:关闭菜单
        closeMenu() {
            this.isOpen = false
        }

    }
}
</script>

<style scoped>
.custom-dropdown {
    position: relative;
    display: inline-block;
}

.menu {
    position: absolute;
    top: 40px;
    left: 0;
    width: 200px;
    padding: 10px;
    border: 1px solid #eee;
    background: #fff;
}
</style>
相关推荐
GuWenyue1 小时前
放弃云端API!一套React+WebGPU本地LLM方案,零数据上传、离线可用
前端·人工智能·前端框架
原则猫3 小时前
函数/变量提升
前端
独泪了无痕3 小时前
Vue3 Hooks使用实战解析
前端·vue.js
shawxlee5 小时前
vue3在public下封装config.js自定义配置动态数据,可在打包后直接修改,方便后端部署及后续维护
前端·javascript·经验分享·vue·团队开发·js·项目优化
用户059540174465 小时前
把记忆存储的回归测试从手工换成 Playwright + GitHub Actions,线上缺陷降低 80%
前端·css
触底反弹5 小时前
🚀 从 DOM0 级到 React 合成事件:前端事件监听的 20 年演进史
前端·react.js·面试
kyriewen5 小时前
我给前端项目的接口请求套了6层保护——才发现以前一直在裸奔
前端·javascript·面试
颜酱5 小时前
04 | 召回前置准备:搭好召回所需的四个数据库
前端·人工智能·后端
郝亚军7 小时前
如何安装webstorm、Node.js和vue CLI
前端·javascript·vue.js
IT_陈寒7 小时前
React的useEffect依赖项把我坑惨了
前端·人工智能·后端