zoukankan      html  css  js  c++  java
  • Vue 实现点击空白处隐藏某节点(三种方式:指令、普通、遮罩)

    在项目中往往会有这样的需求: 弹出框(或Popover)在 show 后,点击空白处可以将其 hide。
    针对此需求,整理了三种实现方式,大家按实际情况选择。

    当然,我们做项目肯定会用到 UI 框架,常见的 Element 中的组件提供了这样的方法。
    但是,就算使用框架,有些时候还是要用到的,比如:

    Element 中的 Popover,当我们想使用手动方式(trigger 触发方式为 manual时)控制它的 show & hide 的时候,就要自己实现这个功能啦。

    第一种方式:最普通的手动监听判断

    <span ref="projectButton">
    	<el-popover v-model="visible" trigger="manual" placement="bottom" @show="show" @hide="hide">
    	  <p>啦啦啦</p>
    	  <el-button slot="reference" type="primary" @click="visible = !visible">show</el-button>
    	</el-popover>
    </span>
    
    
    data () {
     return {
        visible: false
      }
    },
    methods: {
      show () {
        document.addEventListener('click', this.hidePanel, false)
      },
      hide () {
        document.removeEventListener('click', this.hidePanel, false)
      },
      hidePanel (e) {
        if (!this.$refs.projectButton.contains(e.target)) {
          this.visible = false
          this.hide()
        }
      }
    }
    
    

    上面就是在 Popover show 的时候监听 document 的 click 事件,触发进入 hidePanel 方法,判断当前点击的 el 是否在 Popover 内部,如果不在,则手动 hide Popover ,并且移除监听事件。

    这个还是蛮好理解的,我使用的也是这种方式,因为我的项目中需要这种需求的很少(好吧,就一个地方),所以我采用了这种方式。


    第二种方式: 指令

    <template>
     <div>
     <div class="show" v-show="show" v-clickoutside="handleClose">
      显示
     </div>
     </div>
    </template>
     
    <script>
    const clickoutside = {
      // 初始化指令
      bind(el, binding, vnode) {
        function documentHandler(e) {
      	  // 这里判断点击的元素是否是本身,是本身,则返回
          if (el.contains(e.target)) {
            return false;
      }
    	  // 判断指令中是否绑定了函数
          if (binding.expression) {
      	    // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
            binding.value(e);
          }
     }
     	// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
        el.__vueClickOutside__ = documentHandler;
        document.addEventListener('click', documentHandler);
      },
      update() {},
      unbind(el, binding) {
        // 解除事件监听
        document.removeEventListener('click', el.__vueClickOutside__);
        delete el.__vueClickOutside__;
      },
    };
    export default {
      name: 'HelloWorld',
      data() {
        return {
          show: true,
        };
      },
      directives: {clickoutside},
      methods: {
        handleClose(e) {
          this.show = false;
        },
      },
    };
    </script>
     
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    .show {
       100px;
      height: 100px;
      background-color: red;
    }
    </style>
    

    上面这种是网上比较火的一种方式(实际我没有测试过),其实思路还是那个思路 (给document增加一个click事件监听,当发生click事件的时候判断是否点击的当前对象,不是就隐藏),优点就是可以封装成全局/局部的指令,可多处使用。

    下面简单介绍下 vue 指令
    一个指令定义对象可以提供如下几个钩子函数 (均为可选):

    • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
    • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    • unbind:只调用一次,指令与元素解绑时调用。

    第三种方式:遮罩

    <template>
      <div>
        <div class="mask" v-if="showModal" @click="showModal=false"></div>
        <div class="pop" v-if="showModal">
            <button @click="showModal=false" class="btn">点击出现弹框</button>
        </div>
        <button @click="showModal=true" class="btn">点击出现弹框</button>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          showModal: false
        };
      }
    };
    </script>
    
    <style scoped>
    .mask {
      background-color: #000;
      opacity: 0.3;
      position: fixed;
      top: 0;
      left: 0;
       100%;
      height: 100%;
      z-index: 1
    }
    .pop {
      background-color: #fff;
     
      position: fixed;
      top: 100px;
      left: 300px;
       calc(100% - 600px);
      height:calc(100% - 200px);
      z-index: 2
    }
    .btn {
      background-color: #fff;
      border-radius: 4px;
      border: 1px solid blue;
      padding: 4px 12px;
    }
    </style>
    

    上面这个就是添加一个看不见的遮罩替代 document ,点击遮罩就隐藏。但是要注意:mask(遮罩)层的层级(z-index)要比弹出的pop的层级低。


    觉得有帮助的小伙伴点个赞支持下~

    觉得有帮助的小伙伴点个赞~

  • 相关阅读:
    vue+webpack搭建项目基础架构
    vue入门学习篇——父子组件通信
    vue入门学习篇——数据双向绑定原理及简单实现
    vue入门学习篇——挂载点、实例、模版之间的关系
    毫秒转成天、小时、分钟、秒
    可执行jar包的MANIFEST.MF
    fsck系统修复
    HDFS, YARN, HBase, Hive, ZooKeeper端口说明
    解压 tar zxvf 文件名.tar.gz 压缩 tar zcvf 文件名.tar.gz 目标名
    Linux学习笔记之RedHat Enterprise Linux 6.4 使用 Centos 6 的yum源问题
  • 原文地址:https://www.cnblogs.com/zheroXH/p/11724588.html
Copyright © 2011-2022 走看看