Vue指令实现OutClick的示例

 更新时间:2020年11月16日 09:25:26   作者:TMaize  
在一般业务中监听的最多的就是 Click 事件,但是在一些业务比如 Alert 和 Pop 效果时,需要监听在元素外部的点击来关闭弹窗。

原始实现

下面是两种常见的模态框的实现方式

方案一:默认 click 都是放在冒泡阶段,只要在内容区域上添加 click 的阻止冒泡即可

<div class="cover" @click="close">
 <!-- 阻止冒泡 -->
 <div class="content" @click.stop>modal content</div>
</div>

方案二:通过代码判断点击触发的 DOM 是否在内容区域内

<div class="cover" @click="handleClick">
 <div class="content" ref="content">modal content</div>
</div>
handleClick (e) {
 let clickOut = true
 let temp = e.target
 do {
  if (temp === this.$refs.content) {
   clickOut = false
   break
  }
  temp = temp.parentElement
 } while (temp !== document.documentElement)
 console.log(clickOut)
}

指令实现

上面的代码可以解决全屏的模态框点击外部区域关闭。但是还有一种 Pop 的弹出,这种弹出的外部区域不在本组件内,想要实现这种弹出的点击外部区域关闭用上面的方式二也是可以的,只需把 mounted 阶段把 handleClick 事件添加到 body,在 beforeDestroy 上解绑 body 上的点击时间就就可以了。

如果多个组件需要实现这点击外部区域关闭的效果,可以通过 Vue 的指令来进行封装

实现弹窗

<div class="cover">
 <div class="content" v-out-click="close">modal content</div>
</div>

实现弹出

<button @click="popIsShow = true">显示气泡</button>
<div class="pop" v-if="popIsShow" v-out-click="closePop">I'm pop text</div>

指令代码的具体内容如下。有一点比较难受的是指令里面没有地方能存放变量,只好把把这些变量放到了 DOM 上了。还有就是在使用的时候要加上v-的前缀,指令的名字不用带上v-

import outClick from './directive/out-click.js'
Vue.directive(outClick.name, outClick)
const KEY_OUT = '_out_click'
const KEY_OUT_EVENT = '_out_click_event'
const KEY_IN = '_in_click'
const KEY_FLAG = '_in_out_flag'

function removeEvent(el, binding, vnode) {
 el.removeEventListener('click', el[KEY_IN], false)
 window.removeEventListener('click', el[KEY_OUT], false)
 delete el[KEY_IN]
 delete el[KEY_OUT]
 delete el[KEY_OUT_EVENT]
 delete el[KEY_FLAG]
}

function initEvent(el, binding, vnode) {
 // setTimeout 0: 忽略点击外部的按钮初始化该组件时,触发的origin click
 setTimeout(() => {
  el[KEY_OUT] = () => outClick(el)
  el[KEY_IN] = () => inClick(el)
  el[KEY_OUT_EVENT] = binding.value
  el.addEventListener('click', el[KEY_IN], false)
  window.addEventListener('click', el[KEY_OUT], false)
 }, 0)
}

function inClick(el) {
 // 通过事件捕获的顺序作为标志位
 // 最好不要使用阻止冒泡来实现,那样会影响其他的click无法触发
 el[KEY_FLAG] = '1'
}

function outClick(el) {
 if (!el[KEY_FLAG] && el[KEY_OUT_EVENT]) {
  el[KEY_OUT_EVENT]()
 }
 delete el[KEY_FLAG]
}

export default {
 name: 'out-click',
 update: (el, binding, vnode) => {
  if (binding.value === binding.oldValue) {
   return
  }
  removeEvent(el, binding, vnode)
  initEvent(el, binding, vnode)
 },
 bind: initEvent,
 unbind: removeEvent
}

以上就是Vue指令实现OutClick的示例的详细内容,更多关于Vue指令实现OutClick的资料请关注脚本之家其它相关文章!

相关文章

  • vue $router和$route的区别详解

    vue $router和$route的区别详解

    这篇文章主要介绍了vue $router和$route的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Vue组件间传值的实现解析

    Vue组件间传值的实现解析

    组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,这篇文章主要介绍了Vue组件间传值的实现
    2022-09-09
  • vue+iview框架实现左侧动态菜单功能的示例代码

    vue+iview框架实现左侧动态菜单功能的示例代码

    这篇文章主要介绍了vue+iview框架实现左侧动态菜单功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Vue项目安装less和less-loader的详细步骤

    Vue项目安装less和less-loader的详细步骤

    这篇文章主要介绍了Vue项目安装less和less-loader的详细步骤,本文分步骤结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • 用 Vue.js 递归组件实现可折叠的树形菜单(demo)

    用 Vue.js 递归组件实现可折叠的树形菜单(demo)

    通过本文给您演示一下如何有效地使用递归组件,我将通过建立一个可扩展/收缩的树形菜单的来一步步进行。下面通过本文给大家分享用 Vue.js 递归组件实现可折叠的树形菜单,需要的朋友参考下吧
    2017-12-12
  • Vue3-KeepAlive,多个页面使用keepalive方式

    Vue3-KeepAlive,多个页面使用keepalive方式

    这篇文章主要介绍了Vue3-KeepAlive,多个页面使用keepalive方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Vue命令式组件的编写与应用小结

    Vue命令式组件的编写与应用小结

    这篇文章主要介绍了Vue命令式组件的编写与应用小结,在这篇文章中,我会带你了解命令式组件的基本概念,并通过一些简单的示例来展示它们是如何工作的,需要的朋友可以参考下
    2024-03-03
  • 详解webpack编译多页面vue项目的配置问题

    详解webpack编译多页面vue项目的配置问题

    本篇文章主要介绍了详解webpack编译多页面vue项目的配置问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Vue学习笔记之表单输入控件绑定

    Vue学习笔记之表单输入控件绑定

    本篇文章主要介绍了Vue学习笔记之表单输入绑定,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Vue.js的复用组件开发流程完整记录

    Vue.js的复用组件开发流程完整记录

    这篇文章主要给大家介绍了关于Vue.js的复用组件开发流程的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11

最新评论