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>
相关推荐
川冰ICE4 小时前
TypeScript装饰器与元编程实战
前端·javascript·typescript
AI砖家4 小时前
Vue3组件传参大全,各种传参方式的对比
前端·javascript·vue.js
希望永不加班4 小时前
var局部变量类型推断的利弊
java·服务器·前端·javascript·html
threelab5 小时前
Three.js 3D 地图可视化 | 三维可视化 / AI 提示词
前端·javascript·人工智能·3d·着色器
爱怪笑的小杰杰5 小时前
Leaflet 高性能大数据量图圆:彻底解决缩放/拖拽偏移问题
大数据·前端·vue.js·贴图
WL_Aurora5 小时前
大数据技术之SparkCore
大数据·前端·spark·rdd
失眠的咕噜6 小时前
PDA 安卓设备上传多张图片
android·前端·javascript
贵州数擎科技有限公司6 小时前
霓虹沙尘暴的 Three.js 实现
前端·webgl