浅谈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 分号引起的一段调试问题
Jun 18 Javascript
JavaScript格式化数字的函数代码
Nov 30 Javascript
Jquery submit()无法提交问题
Apr 21 Javascript
js格式化货币数据实现代码
Sep 04 Javascript
浅谈angularJS 作用域
Jul 05 Javascript
js查看一个函数的执行时间实例代码
Sep 12 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
Dec 25 Javascript
完美的js图片轮换效果
Feb 05 Javascript
详解Webpack + ES6 最新环境搭建与配置
Jun 04 Javascript
vue父组件异步获取数据传给子组件的方法
Jul 26 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
Sep 05 jQuery
vue3弹出层V3Popup实例详解
Jan 04 Vue.js
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 mssql 数据库分页SQL语句
2008/12/16 PHP
PHP使用pear实现mail发送功能 windows环境下配置pear
2016/04/15 PHP
PHP里的$_GET数组介绍
2019/03/22 PHP
php中关于换行的实例写法
2019/09/26 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
ToolTips JQEURY插件之简洁小提示框效果
2011/11/19 Javascript
jQuery中fadeIn、fadeOut、fadeTo的使用方法(图片显示与隐藏)
2013/05/08 Javascript
jquery获取被勾选的checked(选中)的那一行的3列和4列的值
2013/07/04 Javascript
js将控件隐藏的方法及display属性介绍
2013/07/04 Javascript
JavaScript学习笔记之JS函数
2015/01/22 Javascript
jQuery实用技巧必备(上)
2015/11/02 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
jquery ztree异步搜索(搜叶子)实践
2016/02/25 Javascript
Vue.js组件tabs实现选项卡切换效果
2016/12/01 Javascript
基于JavaScript实现熔岩灯效果导航菜单
2017/01/04 Javascript
微信小程序 radio单选框组件详解及实例代码
2017/01/10 Javascript
基于Vue2的独立构建与运行时构建的差别(详解)
2017/12/06 Javascript
JavaScript实现重力下落与弹性效果的方法分析
2017/12/20 Javascript
JS扩展String.prototype.format字符串拼接的功能
2018/03/09 Javascript
微信jssdk逻辑在vue中的运用详解
2018/11/14 Javascript
基于JS实现简单滑块拼图游戏
2019/10/12 Javascript
Vue + Scss 动态切换主题颜色实现换肤的示例代码
2020/04/27 Javascript
vscode+gulp轻松开发小程序的完整步骤
2020/10/18 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
Python实现抓取网页并且解析的实例
2014/09/20 Python
python executemany的使用及注意事项
2017/03/13 Python
python实现将视频按帧读取到自定义目录
2019/12/10 Python
python检查目录文件权限并修改目录文件权限的操作
2020/03/11 Python
python with语句的原理与用法详解
2020/03/30 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
Nicole Miller官方网站:纽约女装品牌
2019/09/14 全球购物
2019年圣诞节祝福语集锦
2019/12/25 职场文书
pytorch 6 batch_train 批训练操作
2021/05/28 Python
《游戏王:大师决斗》新活动上线 若无符合卡组可免费租用
2022/04/13 其他游戏
Rust中的Struct使用示例详解
2022/08/14 Javascript