浅谈Vue.js中如何实现自定义下拉菜单指令


Posted in Javascript onJanuary 06, 2019

我们利用  Vue.js 的自定义指令能力,来实现一个自定义下拉菜单功能。描述如下:

  1. 点击按钮,弹出下拉菜单。
  2. 点击下拉菜单之外的区域,关闭下拉菜单。

1基础版

html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link rel="stylesheet" type="text/css" href="style.css" rel="external nofollow" >
</head>
<body>

  <div id="app" v-cloak>
    <div class="main" v-outside-click="close">
      <button @click="isShow=!isShow">点击</button>
      <div class="dropDown" v-show="isShow">
        <p>零售新物种:药店和便利店合体之后</p>
      </div>
    </div>
  </div>

<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
<script src="index.js"></script>

</body>
</html>

我们为按钮绑定了 isShow 变量,当点击按钮时,显示 class="dropDown" 的 div 元素。

js:

Vue.directive('outside-click', {
  bind: function (el, binding, vnode) {
    //定义点击函数
    function clickHandler(e) {
      if (el.contains(e.target)) {//如果点击区域在所在指令元素内部,则直接返回
        return false;
      }
      if (binding.expression) {//如果定义了表达式,则执行表达式中的函数
        binding.value(e);
      }
    }

    el.vueOutsideClick = clickHandler;
    document.addEventListener('click', clickHandler);//绑定到 document 的点击事件
  },
  unbind: function (el, binding, vnode) {
    document.removeEventListener('click', el.vueOutsideClick);//解绑
    delete el.vueOutsideClick;//销毁
  }

});

var app = new Vue({
  el: '#app',
  data: {
    isShow: false
  },
  methods: {
    close: function () {
      this.isShow = false;
    }
  }
});

bind 中:

  1. 首先在定义了点击函数,内部逻辑为:如果点击区域在所在指令元素内部,则直接返回;如果定义了表达式,则执行表达式中的函数(示例中是 close)。
  2. 这里用到了 contains 函数, A.contains(B) 是判断元素 A 是否包含了元素 B。
  3. 接着在 el 中定义了一个变量,用于存放刚才定义的点击函数。bind() 与 unbind() 通过 el 变量进行参数传递。
  4. 然后绑定到 document 的点击事件。

unbind 中:

  1. 解绑在 bind 中绑定的点击事件。
  2. 销毁该变量。

css:

[v-cloak] {
  display: none;
}

.main {
  width: 125px;
}

button {
  display: block;
  width: 100%;
  color: #ffffff;
  background-color: #99CC66;
  border: 0;
  padding: 6px;
  text-align: center;
  font-size: 12px;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  outline: none;
}

button:active {
  top: 1px;
  left: 1px;
}

.dropDown {
  width: 100%;
  height: 150px;
  margin: 5px 0;
  font-size: 12px;
  background-color: #ffffff;
  border-radius: 4px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
}

.dropDown p {
  display: inline-block;
  padding: 6px;
}

效果:

浅谈Vue.js中如何实现自定义下拉菜单指令

2  ESC 关闭

现在让我们做个优化,即在按下键盘的 ESC 键时,也能关闭下拉菜单。

js:

bind: function (el, binding, vnode) {
  function clickHandler(e) {
    if (el.contains(e.target) && e.keyCode !== 27) {
      return false;
    }
    ...
  }

  ...
  document.addEventListener('keyup', clickHandler, false);//绑定键盘事件
},
unbind: function (el, binding, vnode) {
    ...
  document.removeEventListener('keyup', el.vueOutsideClick);//解绑
  ...
}

在 bind 函数中,强化了判断,如果点击区域在所在指令元素内部并且没有按下 ESC 键时,才直接返回。即按下  ESC 键时,会执行后续操作(执行表达式中的函数)。

在  unbind 函数中,也解绑了 keyup 事件。

效果:

浅谈Vue.js中如何实现自定义下拉菜单指令

3 ESC 为可选项

我们可以把 ESC 作为可选项,而这可以通过修饰符来实现。

js:

bind: function (el, binding, vnode) {
  //定义点击函数
  function clickHandler(e) {

    //是否开启开关
    var escSwitch = (binding.modifiers && binding.modifiers.esc);

    if (el.contains(e.target)) {//如果点击区域在所在指令元素内部时
      if (escSwitch && e.keyCode === 27) {//带有了 esc 修饰符,则让程序往下执行
      } else {//直接返回
        return false;
      }
    }
    if (binding.expression) {//如果定义了表达式,则执行表达式中的函数
      binding.value(e);
    }
  }

  ...
}

我们通过 binding.modifiers 来判断自定义指令是否设置了 esc 修饰符,然后以此为基础,来编写后续逻辑。

html:

<div id="app" v-cloak>
  <div class="main" v-outside-click.esc="close">
    ...
  </div>
</div>

本文示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js改变鼠标的形状和样式的方法
Mar 31 Javascript
jQuery实现简单的列表式导航菜单效果代码
Aug 31 Javascript
纯JavaScript基于notie.js插件实现消息提示特效
Jan 18 Javascript
原生js编写autoComplete插件
Apr 13 Javascript
PHP捕捉异常中断的方法
Oct 24 Javascript
Javascript 获取鼠标当前的位置实现方法
Oct 27 Javascript
实例详解JavaScript中setTimeout函数的执行顺序
Jul 12 Javascript
原生JavaScript实现Ajax异步请求
Nov 19 Javascript
jquery自定义显示消息数量
Dec 19 jQuery
koa上传excel文件并解析的实现方法
Aug 09 Javascript
JavaScript数组特性与实践应用深入详解
Dec 30 Javascript
vue input标签通用指令校验的实现
Nov 05 Javascript
react-router4按需加载(踩坑填坑)
Jan 06 #Javascript
React 实现拖拽功能的示例代码
Jan 06 #Javascript
Next.js实现react服务器端渲染的方法示例
Jan 06 #Javascript
vue.js引入外部CSS样式和外部JS文件的方法
Jan 06 #Javascript
Bootstrap4 gulp 配置详解
Jan 06 #Javascript
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 #jQuery
node.js连接mysql与基本用法示例
Jan 05 #Javascript
You might like
PHP 操作文件的一些FAQ总结
2009/02/12 PHP
php自动加载的两种实现方法
2010/06/21 PHP
使用VisualStudio开发php的图文设置方法
2010/08/21 PHP
PHP实现伪静态方法汇总
2016/01/13 PHP
浅谈PHP检查数组中是否存在某个值 in_array 函数
2016/06/13 PHP
深入理解PHP JSON数组与对象
2016/07/19 PHP
Javascript select控件操作大全(新增、修改、删除、选中、清空、判断存在等)
2008/12/19 Javascript
jquery trigger伪造a标签的click事件取代window.open方法
2014/06/23 Javascript
JavaScript字符串对象substr方法入门实例(用于截取字符串)
2014/10/16 Javascript
javascript 闭包详解
2015/02/15 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
JavaScript中使用指数方法Math.exp()的简介
2015/06/15 Javascript
对于jQuery性能的一些优化建议
2015/08/13 Javascript
javascript自动恢复文本框点击清除后的默认文本
2016/01/12 Javascript
JS通过Cookie判断页面是否为首次打开
2016/02/05 Javascript
Javascript中内建函数reduce的应用详解
2016/10/20 Javascript
利用浮层使select不可选的实现方法
2016/12/03 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
写一个移动端惯性滑动&amp;回弹Vue导航栏组件 ly-tab
2018/03/06 Javascript
vue 实现LED数字时钟效果(开箱即用)
2019/12/08 Javascript
[08:40]Navi Vs Newbee
2018/06/07 DOTA
python完成FizzBuzzWhizz问题(拉勾网面试题)示例
2014/05/05 Python
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
2015/05/06 Python
在python plt图表中文字大小调节的方法
2019/07/08 Python
详解Python二维数组与三维数组切片的方法
2019/07/18 Python
Python Tornado批量上传图片并显示功能
2020/03/26 Python
Python虚拟环境virtualenv创建及使用过程图解
2020/12/08 Python
Python 找出英文单词列表(list)中最长单词链
2020/12/14 Python
前端实现背景虚化但内容清晰且自适应 的实例代码
2019/08/01 HTML / CSS
电子商务专业个人的自我评价
2013/12/19 职场文书
社区学习雷锋活动总结
2014/04/25 职场文书
政治学专业毕业生求职信
2014/08/11 职场文书
内勤岗位职责
2015/02/10 职场文书
2019年销售人员的职业生涯规划书
2019/03/25 职场文书
Django显示可视化图表的实践
2021/05/10 Python
JS轻量级函数式编程实现XDM三
2022/06/16 Javascript