簡體   English   中英

如何在 Vuejs 中添加 v-click-outside?

[英]How to add v-click-outside in Vuejs?

 <ul class="list-inline" v-if="showSearchHistory"> <li class="list-inline-item list-group-item-primary" v-for="(item, index) in searchHistory.slice(-5).reverse().map((s) => s.trim())":key="index" @click="selectPreviousSearch(index)" > {{ item }} </li> <div class="line-separator"> </div> </ul>

 methods: { enter() { this.selection = this.matches[this.current]; this.open = false; }, onClick() { this.showSearchHistory = true; }, change() { this.showSearchHistory = false; }, inputChanged(event) { if (event.code == "ArrowUp" || event.code == "ArrowDown") return; this.filteredUsers = []; if (event.code == "Enter") return; var filtered = this.users.filter((user) => { return user.text.match(this.search) }); this.isOpen = true this.filteredUsers.push(...filtered) // console.log(this.filteredUsers) }, closeSearch() { this.showSearchHistory = true; }, }
 <input class="form-control bg-light-blue" id="SearchText" type="text" v-model="search" @keydown.enter="enter" @click="onClick" @keyup.enter="processSearch" @input="change" @keyup="inputChanged" @keydown.down="onArrow" @keydown.up="onArrow" @keydown.space="preventLeadingSpace" @focusout="closeSearch" />

我有一個搜索字段,當我點擊搜索時,會顯示 Li 標簽,

現在我需要關閉 Li 標簽,當我在搜索之外單擊時

所以為了關閉 li 標簽,采取了@focusout="closeSearch" 並為此編寫了一種方法,但現在的問題是,即使我點擊 li 標簽,它也會關閉。

這是我在項目中使用的指令:

import Vue from 'vue';

const HAS_WINDOWS = typeof window !== 'undefined';
const HAS_NAVIGATOR = typeof navigator !== 'undefined';
const IS_TOUCH = HAS_WINDOWS && ('ontouchstart' in window || (HAS_NAVIGATOR && navigator.msMaxTouchPoints > 0));
const EVENTS = IS_TOUCH ? ['touchstart'] : ['click'];
const IDENTITY = (item) => item;

const directive = {
  instances: [],
};

function processDirectiveArguments (bindingValue)
{
  const isFunction = typeof bindingValue === 'function';
  if (!isFunction && typeof bindingValue !== 'object')
  {
    throw new Error('v-click-outside: Binding value must be a function or an object');
  }

  return {
    handler: isFunction ? bindingValue : bindingValue.handler,
    middleware: bindingValue.middleware || IDENTITY,
    events: bindingValue.events || EVENTS,
    isActive: !(bindingValue.isActive === false),
  };
}

function onEvent ({ el, event, handler, middleware })
{
  const isClickOutside = event.target !== el && !el.contains(event.target);

  if (!isClickOutside)
  {
    return;
  }

  if (middleware(event, el))
  {
    handler(event, el);
  }
}

function createInstance ({ el, events, handler, middleware })
{
  return {
    el,
    eventHandlers: events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({
        event,
        el,
        handler,
        middleware
      }),
    })),
  };
}

function removeInstance (el)
{
  const instanceIndex = directive.instances.findIndex((instance) => instance.el === el);
  if (instanceIndex === -1)
  {
    // Note: This can happen when active status changes from false to false
    return;
  }

  const instance = directive.instances[instanceIndex];

  instance.eventHandlers.forEach(({ event, handler }) =>
    document.removeEventListener(event, handler)
  );

  directive.instances.splice(instanceIndex, 1);
}

function bind (el, binding)
{
  const { events, handler, middleware, isActive } = processDirectiveArguments(binding.value);

  if (!isActive)
  {
    return;
  }

  const instance = createInstance({
    el,
    events,
    handler,
    middleware
  });

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0)
  );
  directive.instances.push(instance);
}

function update (el, { value, oldValue })
{
  if (JSON.stringify(value) === JSON.stringify(oldValue))
  {
    return;
  }

  const { events, handler, middleware, isActive } = processDirectiveArguments(value);

  if (!isActive)
  {
    removeInstance(el);
    return;
  }

  let instance = directive.instances.find((instance) => instance.el === el);

  if (instance)
  {
    instance.eventHandlers.forEach(({ event, handler }) =>
      document.removeEventListener(event, handler)
    );
    instance.eventHandlers = events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({
        event,
        el,
        handler,
        middleware
      }),
    }));
  }
  else
  {
    instance = createInstance({
      el,
      events,
      handler,
      middleware
    });
    directive.instances.push(instance);
  }

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0)
  );
}

directive.bind = bind;
directive.update = update;
directive.unbind = removeInstance;

Vue.directive('click-outside', directive); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM