浅谈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 相关文章推荐
Javascript 静态页面实现随机显示广告的办法
Nov 17 Javascript
把input初始值不写value的具体实现方法
Jul 04 Javascript
Angularjs基础知识及示例汇总
Jan 22 Javascript
详解JavaScript中jQuery和Ajax以及JSONP的联合使用
Aug 13 Javascript
浅谈使用MVC模式进行JavaScript程序开发
Nov 10 Javascript
jQuery实现背景滑动菜单
Dec 02 Javascript
JavaScript实现大图轮播效果
Jan 11 Javascript
JavaScript中undefined和null的区别
May 03 Javascript
让微信小程序支持ES6中Promise特性的方法详解
Jun 13 Javascript
详解vuex的简单使用
Mar 12 Javascript
vue点击input弹出带搜索键盘并监听该元素的方法
Aug 25 Javascript
原生js实现公告滚动效果
Jan 10 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 多个submit提交表单 处理方法
2009/07/07 PHP
PHP 抓取网页图片并且另存为的实现代码
2010/03/24 PHP
php下尝试使用GraphicsMagick的缩略图功能
2011/01/01 PHP
PHP基于openssl实现的非对称加密操作示例
2019/01/11 PHP
function, new function, new Function之间的区别
2007/03/08 Javascript
写了一个layout,拖动条连贯,内容区可为iframe
2007/08/19 Javascript
面向对象的javascript(笔记)
2009/10/06 Javascript
JavaScript中两个感叹号的作用说明
2011/12/28 Javascript
jQuery表格排序组件-tablesorter使用示例
2014/05/26 Javascript
js 获取元素在页面上的偏移量的方法汇总
2015/04/13 Javascript
详解Vue.js入门环境搭建
2017/03/17 Javascript
jquery.form.js异步提交表单详解
2017/04/25 jQuery
vue动态绑定组件子父组件多表单验证功能的实现代码
2018/05/14 Javascript
vue无限轮播插件代码实例
2019/05/10 Javascript
解决layui-open关闭自身窗口的问题
2019/09/10 Javascript
Vue实现 点击显示再点击隐藏效果(点击页面空白区域也隐藏效果)
2020/01/16 Javascript
JavaScript 装逼指南(js另类写法)
2020/05/10 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
[40:03]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#1EHOME VS Archon
2016/03/02 DOTA
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
Python使用新浪微博API发送微博的例子
2014/04/10 Python
Python元组常见操作示例
2019/02/19 Python
Python3.5常见内置方法参数用法实例详解
2019/04/29 Python
python使用time、datetime返回工作日列表实例代码
2019/05/09 Python
Flask框架学习笔记之使用Flask实现表单开发详解
2019/08/12 Python
python3中rank函数的用法
2019/11/27 Python
win10系统Anaconda和Pycharm的Tensorflow2.0之CPU和GPU版本安装教程
2019/12/03 Python
详解torch.Tensor的4种乘法
2020/09/03 Python
数控专业毕业生求职信
2014/06/12 职场文书
老兵退伍标语
2014/10/07 职场文书
走群众路线剖析材料
2014/10/09 职场文书
幼儿园中班教师个人工作总结
2015/02/06 职场文书
五四青年节活动总结
2015/02/10 职场文书
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers
详解Vue的列表渲染
2021/11/20 Vue.js
Win11如何查看显卡型号 Win11查看显卡型号的方法
2022/08/14 数码科技