Нажмите на раскрывающуюся коробку, как закрыть раскрывающийся ящик

Vue.js

видел раньше5 библиотек Vue.js Я не могу жить безКоторый является первымClick Off to Close, основная функция — инициировать событие, когда пользователь щелкает за пределами элемента.

Цель этой статьи, рукописные пользовательские инструкции для достижения этой функции.

Функция состоит в том, чтобы самостоятельно инкапсулировать раскрывающийся список или инкапсулировать календарь и надеяться, что раскрывающийся список можно будет закрыть, когда вы щелкнете по части не раскрывающегося списка.

下拉框

обычный выпадающий список

Сначала реализовать нормальную раскрывающуюся коробку. То есть коробка + панель. Нажмите на коробку, отобразите или скройте панель.

下拉框

<div id="app">
  <div class="select-box">
    <div class="trigger-head" @click="clickSelect">点击下拉</div>
    <div v-if="isShow" class="trigger-body">我是下拉框</div>
  </div>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
  const vm = new Vue({
    el: "#app",
    data: {
      isShow: false
    },
    methods: {
      clickSelect() {
        this.isShow = !this.isShow;
      }
    }
  });
</script>
<!-- style这里先放后面,毕竟不是说的重点 -->
<style>
  .select-box {
    width: 200px;
    margin-left: 200px;
  }
  .trigger-head {
    border: 1px solid #ccc;
    padding: 10px;
  }
  .trigger-body {
    width: 200px;
    height: 300px;
    background-color: #ccc;
    position: absolute;
  }
</style>

Важно: нажать на улице, закрою панель

Я сначала вставлю код, после прочтения кода я в принципе понимаю

mounted() {
  document.addEventListener("click", (e)=> {
    // 记得在.select-box那边加上ref="selectBox"
    const selectBox = this.$refs.selectBox;
    // 重点来了:selectBox里是否包含点击的元素,不包含点击的元素就隐藏面板
    if (!selectBox.contains(e.target)) {
      this.isShow = false;
    }
  });
},

На самом деле с первого взгляда на код аудитория, вероятно, все поймет.

Событие клика привязывается глобально, а затем передаетсяcontainsЭтот ключевой метод определяет, является ли выбранный элементselectBoxПотомки , если нет, то должно бытьselectBox

Как инкапсулировать пользовательские инструкции в официальные документы

Упакуйте один здесь,clickOutsideИнструкция, которая связывает элемент инструкции, указывает, что щелчок за пределами элемента выполнит соответствующую функцию.

// html那边  <div v-click-outside="hidePanel" ref="selectBox" class="select-box" >
Vue.directive("click-outside", (el, bindings, vnode) => {
  // el就是绑定指令的元素,bindings.expression就是动态参数这里是hide,vnode是绑定指令的元素的虚拟节点,vnode.context就是节点所在的vm实例
  document.addEventListener("click", e => {
    // 点击的是 绑定指令元素么 不是就执行函数
    if (!el.contains(e.target)) {
      let method = bindings.expression;
      vnode.context[method]();
    }
  });
});

// 顺便记得在methods里面添加 hidePanel(){ this.isShow = false }

Хуки для пользовательских директив

Выше, в основном почти, но есть оптимизированная точка, потому что событие связывания являетсяdocument, мы должны развязать в нужное время.

Прочитав документацию на официальном сайте, можно подумать оunbindЭтот хук, как только инструкция будет отвязана, документ автоматически отменит привязку события.

Обратите внимание, что для облегчения отвязки вам необходимо назначить событие клика наel.handle.

Оптимизированный код инструкции выглядит следующим образом:

Vue.directive("click-outside", {
  // el就是绑定指令的元素,bindings.expression就是动态参数这里是hide,vnode是绑定指令的元素的虚拟节点,vnode.context就是节点所在的vm实例
  bind(el, bindings, vnode) {
    el.handle = e => {
      // 点击的是 绑定指令元素么 不是就触发 参数传进来的函数
      if (!el.contains(e.target)) {
        let method = bindings.expression;
        vnode.context[method]();
      }
    };
    document.addEventListener("click", el.handle);
  },
  unbind(el) {
    // 相关事件移除
    document.removeEventListener("click", el.handle);
  }
});

Дополнительно: Инструкция по автофокусу

Я не знаю, нашли ли мы его, даже если бы мыinputдобавить тудаautofocusсвойство, но фокус пропадает на долю секунды, а потом курсора нет.

потому что#appКод внутри входит в фрагмент, компилирует его, а затем заливает в него. Поэтому в начале есть мгновенный фокус, а после того, как он будет влит, эффект фокуса будет недействителен.

Таким образом, если вы хотите выполнить автофокусировку, пакет может быть простой командой, вот прямо официальный сайт.

// <input type="text" v-focus>
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})