[Vue.js2.x]可從外部關閉的下拉選單的自定義指令

Aresn發表於2017-03-07

網頁中有很多常見的下拉彈窗,比如下圖所示的使用者資訊彈窗:

[Vue.js2.x]可從外部關閉的下拉選單的自定義指令

點選使用者頭像和名稱,會彈出一個下拉選單,然後點選頁面中其它空白區域(除了彈窗本身外),彈窗就關閉了。本示例就用自定義指令來實現這樣的需求。

先來分析一下如何實現。

該示例有兩個特點,一是點選下拉選單本身是不會關閉的,二是點選下拉選單以外的所有區域都要關閉。點選所有區域,可以在 document 上繫結 click 事件來實現,同時只要過濾出是否點選的是目標元素內部的元素即可。

程式碼如下,只適用於 Vue.js 2.x

  • index.html:
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>可從外部關閉的下拉選單</title>
      <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
      <div id="app" v-cloak>
          <div class="main" v-clickoutside="handleClose">
              <button @click="show = !show">點選顯示下拉選單</button>
              <div class="dropdown" v-show="show">
                  <p>下拉框的內容,點選外面區域可以關閉</p>
              </div>
          </div>
      </div>
      <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
      <script src="clickoutside.js"></script>
      <script src="index.js"></script>
    </body>
    </html>複製程式碼
  • index.js:

    var app = new Vue({
      el: '#app',
      data: {
          show: false
      },
      methods: {
          handleClose: function () {
              this.show = false;
          }
      }
    });複製程式碼
  • clickoutside.js:

    Vue.directive('clickoutside', {
      bind (el, binding, vnode) {
          function documentHandler (e) {
              if (el.contains(e.target)) {
                  return false;
              }
              if (binding.expression) {
                  binding.value(e);
              }
          }
          el.__vueClickOutside__ = documentHandler;
          document.addEventListener('click', documentHandler);
      },
      unbind (el, binding) {
          document.removeEventListener('click', el.__vueClickOutside__);
          delete el.__vueClickOutside__;
      }
    });複製程式碼
  • style.css:
    [v-cloak] {
      display: none;
    }
    .main{
      width: 125px;
    }
    button{
      display: block;
      width: 100%;
      color: #fff;
      background-color: #39f;
      border: 0;
      padding: 6px;
      text-align: center;
      font-size: 12px;
      border-radius: 4px;
      cursor: pointer;
      outline: none;
      position: relative;
    }
    button:active{
      top: 1px;
      left: 1px;
    }
    .dropdown{
      width: 100%;
      height: 150px;
      margin: 5px 0;
      font-size: 12px;
      background-color: #fff;
      border-radius: 4px;
      box-shadow: 0 1px 6px rgba(0,0,0,.2);
    }
    .dropdown p{
      display: inline-block;
      padding: 6px;
    }複製程式碼

相關文章