浅谈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 相关文章推荐
开发 Internet Explorer 右键功能表(ContextMenu)
Jul 03 Javascript
JavaScript DOM进阶方法
Apr 13 Javascript
Javascript中typeof 用法小结
May 12 Javascript
javascript中html字符串转化为jquery dom对象的方法
Aug 27 Javascript
4种JavaScript实现简单tab选项卡切换的方法
Jan 06 Javascript
JavaScript 正则表达式中global模式的特性
Feb 25 Javascript
温习Javascript基础语法之词法结构
May 31 Javascript
JS实现动画兼容性的transition和transform实例分析
Dec 13 Javascript
JS实现数组按升序及降序排列的方法
Apr 26 Javascript
AngularJS中使用ngModal模态框实例
May 27 Javascript
详解基于mpvue微信小程序下载远程图片到本地解决思路
May 16 Javascript
JavaScript实现网页跨年倒计时
Dec 02 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网站来路获取代码(针对搜索引擎)
2010/06/08 PHP
php入门学习知识点七 PHP函数的基本应用
2011/07/14 PHP
php笔记之:php数组相关函数的使用
2013/04/26 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
2014/11/19 PHP
ajax+php控制所有后台函数调用
2015/07/15 PHP
Yii2框架dropDownList下拉菜单用法实例分析
2016/07/18 PHP
PHP7安装Redis扩展教程【Linux与Windows平台】
2016/09/30 PHP
用于节点操作的API,颠覆原生操作HTML DOM节点的API
2010/12/11 Javascript
jquery特效 幻灯片效果示例代码
2013/07/16 Javascript
Visual Studio中js调试的方法图解
2014/06/30 Javascript
JavaScipt选取文档元素的方法(推荐)
2016/08/05 Javascript
Canvas 绘制粒子动画背景
2017/02/15 Javascript
Angularjs 根据一个select的值去设置另一个select的值方法
2018/08/13 Javascript
详解如何配置vue-cli3.0的vue.config.js
2018/08/23 Javascript
NodeJS如何实现同步的方法示例
2018/08/24 NodeJs
小程序如何写动态标签的实现方法
2020/02/05 Javascript
[02:38]2018年度DOTA2最佳劣单位选手-完美盛典
2018/12/17 DOTA
Python松散正则表达式用法分析
2016/04/29 Python
使用Python进行体育竞技分析(预测球队成绩)
2019/05/16 Python
python打包exe开机自动启动的实例(windows)
2019/06/28 Python
python实现的生成word文档功能示例
2019/08/23 Python
python 读取数据库并绘图的实例
2019/12/03 Python
Python进阶之迭代器与迭代器切片教程
2020/01/29 Python
PyTorch中Tensor的数据统计示例
2020/02/17 Python
PyTorch中model.zero_grad()和optimizer.zero_grad()用法
2020/06/24 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
美国Lolё官网:购买大胆而美丽的女性运动服装
2017/05/22 全球购物
华纳兄弟工作室的官方授权商店:WB Shop
2018/11/30 全球购物
英国Iceland杂货店:网上食品购物
2020/12/16 全球购物
数学系个人求职信范文
2014/01/30 职场文书
幼儿学前班评语
2014/12/29 职场文书
质量保证书格式模板
2015/02/27 职场文书
党员志愿者服务倡议书
2015/04/29 职场文书
慰问信(范文3篇)
2019/10/23 职场文书
CSS3常见动画的实现方式
2021/04/14 HTML / CSS
Python线程池与GIL全局锁实现抽奖小案例
2022/04/13 Python