怎么点击下拉框外面关闭下拉框

简介: 怎么点击下拉框外面关闭下拉框

怎么点击下拉框外面关闭下拉框


之前看到我不能没有的 5 个 Vue.js 库,里面第一个就是Click Off to Close,最主要功能就是,在用户点击元素之外的时候触发一个事件。

此文的目标,手写自定义指令实现此功能。

功能比如自己封装一个下拉框,或者封装一个日历,希望在点击非下拉框部分,能关闭下拉框。


网络异常,图片无法展示
|

普通的下拉框

先实现一个普通的下拉框。 就是,一个框 + 一个面板。 点击框,显示或隐藏面板。


网络异常,图片无法展示
|

<div id="app">
  <div class="select-box">
    <div class="trigger-head" @click="clickSelect">点击下拉</div>
    <div v-if="isShow" class="trigger-body">我是下拉框</div>
  </div>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
  const vm = new Vue({
    el: "#app",
    data: {
      isShow: false
    },
    methods: {
      clickSelect() {
        this.isShow = !this.isShow;
      }
    }
  });
</script>
<!-- style这里先放后面,毕竟不是说的重点 -->
<style>
  .select-box {
    width: 200px;
    margin-left: 200px;
  }
  .trigger-head {
    border: 1px solid #ccc;
    padding: 10px;
  }
  .trigger-body {
    width: 200px;
    height: 300px;
    background-color: #ccc;
    position: absolute;
  }
</style>

重点:点击外面就会关闭面板

我先贴下代码,看完代码,基本就明白了

mounted() {
  document.addEventListener("click", (e)=> {
    // 记得在.select-box那边加上ref="selectBox"
    const selectBox = this.$refs.selectBox;
    // 重点来了:selectBox里是否包含点击的元素,不包含点击的元素就隐藏面板
    if (!selectBox.contains(e.target)) {
      this.isShow = false;
    }
  });
},

代码一看,其实看客们大约就明白了。

click 事件绑定在全局,然后通过contains这个关键性的方法,判断点击的元素是不是selectBox的后代,要不是的话,就肯定点在了selectBox的外面,顺道就隐藏面板。至此,最关键性的逻辑就搞定了。

封装成自定义指令

最核心的逻辑就是上面了。 接下来就是封装成一个指令,专门处理这种,点击元素之外触发某种操作。

官方文档怎么封装自定义指令

这里封装一个,clickOutside的指令,绑定指令的元素,表示点击元素之外的地方就会执行相应的函数。

// html那边  <div v-click-outside="hidePanel" ref="selectBox" class="select-box" >
Vue.directive("click-outside", (el, bindings, vnode) => {
  // el就是绑定指令的元素,bindings.expression就是动态参数这里是hide,vnode是绑定指令的元素的虚拟节点,vnode.context就是节点所在的vm实例
  document.addEventListener("click", e => {
    // 点击的是 绑定指令元素么 不是就执行函数
    if (!el.contains(e.target)) {
      let method = bindings.expression;
      vnode.context[method]();
    }
  });
});
// 顺便记得在methods里面添加 hidePanel(){ this.isShow = false }

自定义指令的钩子

上面基本差不多了,但是还有个优化的点,因为绑定事件是在document上,我们应该择时解绑。

在阅读完官网的文档之后,可以想到unbind这个钩子,一旦指令解绑,document 也就会自动解绑事件。

这里注意,为了方便解绑,所以需要将点击事件赋值给el.handle

优化之后的指令代码如下:

Vue.directive("click-outside", {
  // el就是绑定指令的元素,bindings.expression就是动态参数这里是hide,vnode是绑定指令的元素的虚拟节点,vnode.context就是节点所在的vm实例
  bind(el, bindings, vnode) {
    el.handle = e => {
      // 点击的是 绑定指令元素么 不是就触发 参数传进来的函数
      if (!el.contains(e.target)) {
        let method = bindings.expression;
        vnode.context[method]();
      }
    };
    document.addEventListener("click", el.handle);
  },
  unbind(el) {
    // 相关事件移除
    document.removeEventListener("click", el.handle);
  }
});

附加:自动聚焦的指令

不知道有没有发现,即便我们在input那边加上autofocus属性,但聚焦一瞬即过,然后就没有光标了。

因为#app里面的代码进入了一次fragment,编译好之后,然后再倒进去。所以初始有一瞬间的聚焦,再倒进去之后,聚焦效果就会失效。

于是呢,要是想要自动聚焦的效果,可以封装个简单的指令,这边直接用官网的。

// <input type="text" v-focus>
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})


目录
相关文章
Navicate如何全部选中表,点击表,然后移动到右侧,右侧可以选中,实现拖拽
Navicate如何全部选中表,点击表,然后移动到右侧,右侧可以选中,实现拖拽
|
7月前
在viewWillAppear函数中禁止左滑,viewWillDisappear开启左滑动产生进入下一个页面来回滑动造成无法点击点击按钮问题
在viewWillAppear函数中禁止左滑,viewWillDisappear开启左滑动产生进入下一个页面来回滑动造成无法点击点击按钮问题
39 0
点击添加按钮弹框动态添加内容并且拼接在页面
点击添加按钮弹框动态添加内容并且拼接在页面
37 0
|
JavaScript 前端开发
右下角点击页面回顶部组件
右下角点击页面回顶部组件
70 1
右下角点击页面回顶部组件
|
开发者
jeDate日期控件的使用以及选中后点确定按钮关闭功能
jeDate日期控件的使用以及选中后点确定按钮关闭功能
162 0
selenium+python:点击元素、alert弹框、鼠标操作(左键点击、右键点击、双击、鼠标悬浮)、下拉选项框、窗口切换等操作的处
selenium+python:点击元素、alert弹框、鼠标操作(左键点击、右键点击、双击、鼠标悬浮)、下拉选项框、窗口切换等操作的处
|
JSON 小程序 JavaScript
小程序地图插入图标后 怎么实现点击图标弹出窗口
小程序地图插入图标后 怎么实现点击图标弹出窗口
108 0
tab栏切换制作(点击那一栏显示那一栏的内容,其他栏的内容隐藏)
tab栏切换制作(点击那一栏显示那一栏的内容,其他栏的内容隐藏)
tab栏切换制作(点击那一栏显示那一栏的内容,其他栏的内容隐藏)