Vue实现下拉菜单栏

6,545 阅读3分钟

实际网站之中我们常见到hover到一个标签跳出它所对应菜单栏,今天小编介绍一下用Vue自定义一个指令去实现该操作。这边小编录屏软件有点问题,鼠标看不见,懂意思就好。


分析demo

  • 鼠标触碰上去菜单内容显示

  • 悬停在菜单处不消失

  • 鼠标移至其他区域菜单栏消失

  • 重点:自定义指令用法、Vue渐变标签

有关自定义指令

我们通过创建自定义指令去提供一些方法供DOM元素直接使用,具体文档可见Vue详细文档,小编这边只是粗略介绍了几个常用的,详细可见文档vue自定义指令

  • 四种钩子函数
    • bind:指令第一次绑定到元素时调用。

    • unbind:只调用一次,指令与元素解绑时调用。(当使用指令DOM元素删除时生效)


  • 钩子函数参数
    • el:指令所绑定的DOM元素

    • binding:自定义标签所含的一个对象包含

      • name:指令名
      • value:指令所绑定的值(v-onoutside="handleClose"),案例中这样绑定了一个方法传到指令对象之中。
      • vnode:Vue 编译生成的虚拟节点。虚拟节点还是需要好好理解一下的,找到了一篇比较好的文章大家可以看一下。说说VNode节点

代码实现

一、首先我们自定义一个组件,通过v-show去响应菜单栏的显示

Vue.component('nav-menu', {
   template:`\
      <div class="main" v-onoutside="handleClose" @click="testUnbind" v-if="flag">\
          <button @mouseover="show = !show">hover我显示下拉菜单</button>\
          <transition name="gradualChange">
              <div  class="dropdown" v-show="show">\
                  <p>菜单栏内容,移开到其他区域消失</p>\
              </div>\
          <transition/>\
          </div>
          `,
          data() {
              return {
                  show: false,
                  flag: true
              }
          },
          methods: {
              handleClose() {
                  this.show = false;
              },
              testUnbind() {
                  this.flag = false;
              }
          }
  });

二、那么现在我们所需要解决的问题就是除了他俩之外的位置都对让handleClose函数执行,先说明代码中的几个点

  • 方法传入的参数e: 该方法绑定到了document的鼠标事件上,e用来监听鼠标

  • el.contains(e.target): DOM元素的contains方法,参数是调用者的子级的话返回true

  • binding.value(): 在这个案例之中是传入的handleClose方法 —— v-onoutside="handleClose"

  • binding.expression: 判定有无回调返回的是回调函数名

  • 增加该案例的实用化增加了一个DOM元素消除时将绑定事件消除

      Vue.directive('onoutside', {
          bind: function(el, binding, vnode) {
              // e为监听鼠标的参数
              function documentHandler(e) {
                  // 判断区域
                  if(el.contains(e.target)) {
                      return;
                  }
                  // 判断有无回调  有则执行  
                  if(binding.expression) {
                      binding.value();
                  }
              }
              el._vueonOutside_ = documentHandler;
              // 绑定该方法到document上
              document.addEventListener('mouseover', documentHandler);
          },
          // 当节点删除时注销掉事件
          unbind: function(el, binding) {
              document.removeEventListener('mouseover', el._vueonOutside_);
              delete el._vueonOutside_;
          }
      });

具体样式小编就不在这边写上了可以在github上查看一下完整的demo。 github地址

Vue过渡

demo动图中可以看到给盒子增加了渐入渐出的效果,Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。我们可以通过过渡标签包裹来增加渐变样式,那么下面是Vue中提供的6种状态,再结合他所归类的图我们更加好理解。

ending...