Phát hiện phần tử bên ngoài nhấp chuột


120

Làm cách nào để phát hiện một nhấp chuột bên ngoài phần tử của tôi? Tôi đang sử dụng Vue.js nên nó sẽ nằm ngoài phần tử mẫu của tôi. Tôi biết cách làm điều đó trong Vanilla JS, nhưng tôi không chắc liệu có cách nào thích hợp hơn để làm điều đó không khi tôi đang sử dụng Vue.js?

Đây là giải pháp cho sự kiện Vanilla JS: Javascript Detect Click bên ngoài div

Tôi đoán tôi có thể sử dụng cách tốt hơn để truy cập phần tử?


Các thành phần Vue được cách ly. vì vậy việc phát hiện những thay đổi bên ngoài là điều không cần thiết và sử dụng mẫu chống.
Raj Kamal

Cảm ơn. Tôi không chắc chắn về cách triển khai nó trong một thành phần Vue. Vẫn phải có một số thực hành tốt nhất cho mô hình chống?

Thành phần Vue.js được tách biệt, điều đó đúng, nhưng có các phương pháp khác nhau để giao tiếp giữa cha và con. Vì vậy, thay vì hỏi để phát hiện một bên ngoài sự kiện của một phần tử, bạn nên xác định nếu bạn muốn để phát hiện các yếu tố bên trong một thành phần, từ các thành phần cha mẹ, từ một số trẻ em, hoặc bất cứ mối quan hệ giữa các thành phần là
Yerko Palma

Cảm ơn vì bạn đã phản hồi. Bạn có một số ví dụ hoặc liên kết mà tôi có thể theo dõi không?

github.com/si samplesmiler/vue-clickaway có thể đơn giản hóa công việc của bạn
Raj Kamal

Câu trả lời:


96

Có thể được giải quyết một cách dễ dàng bằng cách thiết lập một chỉ thị tùy chỉnh một lần:

Vue.directive('click-outside', {
  bind () {
      this.event = event => this.vm.$emit(this.expression, event)
      this.el.addEventListener('click', this.stopProp)
      document.body.addEventListener('click', this.event)
  },   
  unbind() {
    this.el.removeEventListener('click', this.stopProp)
    document.body.removeEventListener('click', this.event)
  },

  stopProp(event) { event.stopPropagation() }
})

Sử dụng:

<div v-click-outside="nameOfCustomEventToCall">
  Some content
</div>

Trong thành phần:

events: {
  nameOfCustomEventToCall: function (event) {
    // do something - probably hide the dropdown menu / modal etc.
  }
}

Demo làm việc trên JSFiddle với thông tin bổ sung về các cảnh báo:

https://jsfiddle.net/Linusborg/yzm8t8jq/


3
Tôi đã sử dụng vue clickaway, nhưng tôi nghĩ rằng giải pháp của bạn ít nhiều giống nhau. Cảm ơn.

56
Cách tiếp cận này không hoạt động nữa trong Vue.js 2. Lệnh gọi self.vm. $ phát ra thông báo lỗi.
northernman

3
Sử dụng @blur cũng là một tùy chọn và giúp bạn dễ dàng đưa ra cùng một kết quả hơn: <input @ dim = "hide"> where hide: function () {this.isActive = false; }
Craws

1
Câu trả lời nên được chỉnh sửa để nói rằng tôi chỉ dành cho Vue.js 1
Stéphane Gerber

167

Có một giải pháp mà tôi đã sử dụng, dựa trên câu trả lời của Linus Borg và hoạt động tốt với vue.js 2.0.

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    el.clickOutsideEvent = function (event) {
      // here I check that click was outside the el and his children
      if (!(el == event.target || el.contains(event.target))) {
        // and if it did, call method provided in attribute value
        vnode.context[binding.expression](event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
});

Bạn liên kết với nó bằng cách sử dụng v-click-outside:

<div v-click-outside="doStuff">

Đây là một bản demo nhỏ

Bạn có thể tìm thêm một số thông tin về các lệnh tùy chỉnh và ý nghĩa của el, binding, vnode trong https://vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments


8
Đã hoạt động, nhưng trong Vue 2.0 các chỉ thị không còn thể hiện nữa, vì vậy điều này không được xác định. vuejs.org/v2/guide/migration.html#Custom-Directives-simplified . Tôi không có manh mối tại sao trò chơi này hoạt động hoặc khi nào việc đơn giản hóa này được thực hiện. (Để giải quyết, hãy thay thế "this" bằng "el" để liên kết sự kiện với phần tử)
Busata

1
Nó hoạt động có thể là do cửa sổ được chuyển thành "this". Tôi đã sửa câu trả lời. Cảm ơn bạn đã chỉ ra lỗi này.
MadisonTrash

8
Có cách nào để loại trừ phần tử cụ thể bên ngoài không? Ví dụ, tôi có một nút bên ngoài để mở phần tử này và vì nó kích hoạt cả hai phương thức nên không có gì xảy ra.
Žilvinas

5
Bạn có thể vui lòng giải thích vnode.context [bind.expression] (event); ?
Sainath SR

1
làm cách nào để thay đổi điều này để một biểu thức có thể được sử dụng thay vì một phương thức trong v-click-external được kích hoạt?
raphadko

50

Thêm tabindexthuộc tính vào thành phần của bạn để nó có thể được tập trung và thực hiện những việc sau:

<template>
    <div
        @focus="handleFocus"
        @focusout="handleFocusOut"
        tabindex="0"
    >
      SOME CONTENT HERE
    </div>
</template>

<script>
export default {    
    methods: {
        handleFocus() {
            // do something here
        },
        handleFocusOut() {
            // do something here
        }
    }
}
</script>

4
Ái chà! Tôi thấy đây là giải pháp ngắn gọn và sạch sẽ nhất. Cũng là cái duy nhất hoạt động trong trường hợp của tôi.
Matt Komarnicki

3
Chỉ để thêm vào điều này, việc đặt tabindex là -1 sẽ ngăn hộp đánh dấu xuất hiện khi bạn nhấp vào phần tử, nhưng nó vẫn cho phép div có thể lấy tiêu điểm.
Colin

1
Vì một số lý do tabindex -1 không ẩn đường viền đối với tôi, vì vậy tôi chỉ thêm outline: none;vào tiêu điểm cho phần tử.
Art3mix

1
làm thế nào chúng ta có thể áp dụng điều này cho một điều hướng bên ngoài canvas trình chiếu trên màn hình? Tôi không thể cung cấp cho các tập trung sidenav trừ khi nó được nhấp,
Charles Okwuagwu

1
Đây là cách mạnh mẽ nhất hoàn toàn. Cảm ơn bạn! :)
Canet Robern

23

Có hai gói có sẵn trong cộng đồng cho nhiệm vụ này (cả hai đều được duy trì):


8
vue-clickawaygói giải quyết vấn đề của tôi một cách hoàn hảo. Cảm ơn
Abdalla Arbab

1
Còn rất nhiều đồ thì sao? Mỗi mục có sự kiện nhấp chuột bên ngoài sẽ kích hoạt sự kiện trên mỗi nhấp chuột. Thật tuyệt khi bạn tạo hộp thoại và khủng khiếp khi bạn tạo thư viện. Trong thời đại không phải thành phần, chúng tôi đang nghe nhấp chuột từ tài liệu và kiểm tra xem phần tử nào đã được nhấp. Nhưng bây giờ nó là một nỗi đau.
br.

@Julien Le Coupanec Tôi thấy giải pháp này là tốt nhất cho đến nay! Cảm ơn rất nhiều cho việc chia sẻ nó!
Manuel Abascal

7

Điều này phù hợp với tôi với Vue.js 2.5.2:

/**
 * Call a function when a click is detected outside of the
 * current DOM node ( AND its children )
 *
 * Example :
 *
 * <template>
 *   <div v-click-outside="onClickOutside">Hello</div>
 * </template>
 *
 * <script>
 * import clickOutside from '../../../../directives/clickOutside'
 * export default {
 *   directives: {
 *     clickOutside
 *   },
 *   data () {
 *     return {
         showDatePicker: false
 *     }
 *   },
 *   methods: {
 *     onClickOutside (event) {
 *       this.showDatePicker = false
 *     }
 *   }
 * }
 * </script>
 */
export default {
  bind: function (el, binding, vNode) {
    el.__vueClickOutside__ = event => {
      if (!el.contains(event.target)) {
        // call method provided in v-click-outside value
        vNode.context[binding.expression](event)
        event.stopPropagation()
      }
    }
    document.body.addEventListener('click', el.__vueClickOutside__)
  },
  unbind: function (el, binding, vNode) {
    // Remove Event Listeners
    document.removeEventListener('click', el.__vueClickOutside__)
    el.__vueClickOutside__ = null
  }
}

Cảm ơn bạn vì ví dụ này. Đã kiểm tra điều này trên vue 2.6. Có một số cách khắc phục, trong phương thức hủy liên kết, bạn phải khắc phục một số vấn đề bằng cách này (bạn quên thuộc tính body trong phương thức hủy liên kết): document.body.removeEventListener ('click', el .__ vueClickOutside__); nếu không - nó sẽ tạo ra nhiều trình nghe sự kiện sau mỗi lần tạo lại thành phần (làm mới trang);
Alexey Shabramov

7
export default {
  bind: function (el, binding, vNode) {
    // Provided expression must evaluate to a function.
    if (typeof binding.value !== 'function') {
      const compName = vNode.context.name
      let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`
      if (compName) { warn += `Found in component '${compName}'` }

      console.warn(warn)
    }
    // Define Handler and cache it on the element
    const bubble = binding.modifiers.bubble
    const handler = (e) => {
      if (bubble || (!el.contains(e.target) && el !== e.target)) {
        binding.value(e)
      }
    }
    el.__vueClickOutside__ = handler

    // add Event Listeners
    document.addEventListener('click', handler)
  },

  unbind: function (el, binding) {
    // Remove Event Listeners
    document.removeEventListener('click', el.__vueClickOutside__)
    el.__vueClickOutside__ = null

  }
}

5

Tôi đã kết hợp tất cả các câu trả lời (bao gồm một dòng từ vue-clickaway) và đưa ra giải pháp này phù hợp với tôi:

Vue.directive('click-outside', {
    bind(el, binding, vnode) {
        var vm = vnode.context;
        var callback = binding.value;

        el.clickOutsideEvent = function (event) {
            if (!(el == event.target || el.contains(event.target))) {
                return callback.call(vm, event);
            }
        };
        document.body.addEventListener('click', el.clickOutsideEvent);
    },
    unbind(el) {
        document.body.removeEventListener('click', el.clickOutsideEvent);
    }
});

Sử dụng trong thành phần:

<li v-click-outside="closeSearch">
  <!-- your component here -->
</li>

Khá nhiều giống như câu trả lời @MadisonTrash dưới đây
retrovertigo

3

Tôi đã cập nhật câu trả lời của MadisonTrash để hỗ trợ Mobile Safari (không có clicksự kiện, touchendphải được sử dụng thay thế). Điều này cũng kết hợp kiểm tra để sự kiện không được kích hoạt bằng cách kéo trên thiết bị di động.

Vue.directive('click-outside', {
    bind: function (el, binding, vnode) {
        el.eventSetDrag = function () {
            el.setAttribute('data-dragging', 'yes');
        }
        el.eventClearDrag = function () {
            el.removeAttribute('data-dragging');
        }
        el.eventOnClick = function (event) {
            var dragging = el.getAttribute('data-dragging');
            // Check that the click was outside the el and its children, and wasn't a drag
            if (!(el == event.target || el.contains(event.target)) && !dragging) {
                // call method provided in attribute value
                vnode.context[binding.expression](event);
            }
        };
        document.addEventListener('touchstart', el.eventClearDrag);
        document.addEventListener('touchmove', el.eventSetDrag);
        document.addEventListener('click', el.eventOnClick);
        document.addEventListener('touchend', el.eventOnClick);
    }, unbind: function (el) {
        document.removeEventListener('touchstart', el.eventClearDrag);
        document.removeEventListener('touchmove', el.eventSetDrag);
        document.removeEventListener('click', el.eventOnClick);
        document.removeEventListener('touchend', el.eventOnClick);
        el.removeAttribute('data-dragging');
    },
});

3

Tôi sử dụng mã này:

nút ẩn

 <a @click.stop="visualSwitch()"> show hide </a>

phần tử hiển thị

<div class="dialog-popup" v-if="visualState" @click.stop=""></div>

kịch bản

data () { return {
    visualState: false,
}},
methods: {
    visualSwitch() {
        this.visualState = !this.visualState;
        if (this.visualState)
            document.addEventListener('click', this.visualState);
        else
            document.removeEventListener('click', this.visualState);
    },
},

Cập nhật: gỡ bỏ đồng hồ; thêm ngừng truyền bá


2

Tôi ghét các chức năng bổ sung nên ... đây là một giải pháp vue tuyệt vời mà không có các phương thức vue bổ sung, chỉ var

  1. tạo phần tử html, đặt điều khiển và chỉ thị
    <p @click="popup = !popup" v-out="popup">

    <div v-if="popup">
       My awesome popup
    </div>
  1. tạo một var trong dữ liệu như
data:{
   popup: false,
}
  1. thêm chỉ thị vue. nó là
Vue.directive('out', {

    bind: function (el, binding, vNode) {
        const handler = (e) => {
            if (!el.contains(e.target) && el !== e.target) {
                //and here is you toggle var. thats it
                vNode.context[binding.expression] = false
            }
        }
        el.out = handler
        document.addEventListener('click', handler)
    },

    unbind: function (el, binding) {
        document.removeEventListener('click', el.out)
        el.out = null
    }
})

2

Nếu bạn đang tìm kiếm cụ thể một lần nhấp bên ngoài phần tử nhưng vẫn trong phần tử gốc, bạn có thể sử dụng

<div class="parent" @click.self="onParentClick">
  <div class="child"></div>
</div>

Tôi sử dụng điều này cho các phương thức.


1

Bạn có thể đăng ký hai trình nghe sự kiện cho sự kiện nhấp chuột như thế này

document.getElementById("some-area")
        .addEventListener("click", function(e){
        alert("You clicked on the area!");
        e.stopPropagation();// this will stop propagation of this event to upper level
     }
);

document.body.addEventListener("click", 
   function(e) {
           alert("You clicked outside the area!");
         }
);

Cảm ơn. Tôi biết điều này, nhưng có vẻ như phải có cách tốt hơn để làm điều này trong Vue.js?

ĐỒNG Ý! Hãy để một số thiên tài vue.js trả lời :)
saravanakumar

1
  <button 
    class="dropdown"
    @click.prevent="toggle"
    ref="toggle"
    :class="{'is-active': isActiveEl}"
  >
    Click me
  </button>

  data() {
   return {
     isActiveEl: false
   }
  }, 
  created() {
    window.addEventListener('click', this.close);
  },
  beforeDestroy() {
    window.removeEventListener('click', this.close);
  },
  methods: {
    toggle: function() {
      this.isActiveEl = !this.isActiveEl;
    },
    close(e) {
      if (!this.$refs.toggle.contains(e.target)) {
        this.isActiveEl = false;
      }
    },
  },

Cảm ơn, hoạt động hoàn hảo và nếu bạn chỉ cần nó một khi không cần thêm thư viện
Marian Klühspies

1

Câu trả lời ngắn gọn: Điều này nên được thực hiện với Chỉ thị tùy chỉnh .

Có rất nhiều câu trả lời tuyệt vời ở đây cũng nói lên điều này, nhưng hầu hết các câu trả lời tôi đã thấy được chia nhỏ khi bạn bắt đầu sử dụng rộng rãi ngoài nhấp chuột (đặc biệt là nhiều lớp hoặc có nhiều loại trừ). Tôi đã viết một bài báo trên phương tiện nói về các sắc thái của Chỉ thị tùy chỉnh và cách triển khai cụ thể của Chỉ thị này. Nó có thể không bao gồm tất cả các trường hợp cạnh nhưng nó đã bao gồm tất cả những gì tôi đã nghĩ ra.

Điều này sẽ giải thích cho nhiều ràng buộc, nhiều cấp độ loại trừ phần tử khác và cho phép trình xử lý của bạn chỉ quản lý "logic nghiệp vụ".

Đây là mã cho ít nhất phần định nghĩa của nó, hãy xem bài viết để được giải thích đầy đủ.

var handleOutsideClick={}
const OutsideClick = {
  // this directive is run on the bind and unbind hooks
  bind (el, binding, vnode) {
    // Define the function to be called on click, filter the excludes and call the handler
    handleOutsideClick[el.id] = e => {
      e.stopPropagation()
      // extract the handler and exclude from the binding value
      const { handler, exclude } = binding.value
      // set variable to keep track of if the clicked element is in the exclude list
      let clickedOnExcludedEl = false
      // if the target element has no classes, it won't be in the exclude list skip the check
      if (e.target._prevClass !== undefined) {
        // for each exclude name check if it matches any of the target element's classes
        for (const className of exclude) {
          clickedOnExcludedEl = e.target._prevClass.includes(className)
          if (clickedOnExcludedEl) {
            break // once we have found one match, stop looking
          }
        }
      }
      // don't call the handler if our directive element contains the target element
      // or if the element was in the exclude list
      if (!(el.contains(e.target) || clickedOnExcludedEl)) {
        handler()
      }
    }
    // Register our outsideClick handler on the click/touchstart listeners
    document.addEventListener('click', handleOutsideClick[el.id])
    document.addEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = e => {
      //this is an option but may not work right with multiple handlers
      if (e.keyCode === 27) {
        // TODO: there are minor issues when escape is clicked right after open keeping the old target
        handleOutsideClick[el.id](e)
      }
    }
  },
  unbind () {
    // If the element that has v-outside-click is removed, unbind it from listeners
    document.removeEventListener('click', handleOutsideClick[el.id])
    document.removeEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = null //Note that this may not work with multiple listeners
  }
}
export default OutsideClick

1

Tôi đã làm điều đó theo một cách hơi khác bằng cách sử dụng một hàm trong create ().

  created() {
      window.addEventListener('click', (e) => {
        if (!this.$el.contains(e.target)){
          this.showMobileNav = false
        }
      })
  },

Bằng cách này, nếu ai đó nhấp vào bên ngoài phần tử, thì trong trường hợp của tôi, điều hướng di động sẽ bị ẩn.

Hi vọng điêu nay co ich!


1

Đã có nhiều câu trả lời cho câu hỏi này và hầu hết chúng đều dựa trên ý tưởng chỉ thị tùy chỉnh tương tự. Vấn đề với cách tiếp cận này là người ta phải truyền một hàm phương thức cho chỉ thị và không thể trực tiếp viết mã như trong các sự kiện khác.

Tôi đã tạo một gói mới vue-on-clickoutkhác. Kiểm tra nó tại:

Nó cho phép một người viết v-on:clickoutgiống như bất kỳ sự kiện nào khác. Ví dụ, bạn có thể viết

<div v-on:clickout="myField=value" v-on:click="myField=otherValue">...</div>

Và nó hoạt động.

Cập nhật

vue-on-clickout hiện hỗ trợ Vue 3!


0

Chỉ cần nếu ai đó đang tìm cách ẩn phương thức khi nhấp vào bên ngoài phương thức. Vì modal thường có trình bao bọc của nó với lớp modal-wraphoặc bất cứ thứ gì bạn đặt tên cho nó, bạn có thể đặt @click="closeModal"trên trình bao bọc. Sử dụng xử lý sự kiện được nêu trong tài liệu vuejs, bạn có thể kiểm tra xem mục tiêu được nhấp nằm trên trình bao bọc hay trên phương thức.

methods: {
  closeModal(e) {
    this.event = function(event) {
      if (event.target.className == 'modal-wrap') {
        // close modal here
        this.$store.commit("catalog/hideModal");
        document.body.removeEventListener("click", this.event);
      }
    }.bind(this);
    document.body.addEventListener("click", this.event);
  },
}
<div class="modal-wrap" @click="closeModal">
  <div class="modal">
    ...
  </div>
<div>


0

@Denis Danilenko giải pháp phù hợp với tôi, đây là những gì tôi đã làm: Bằng cách tôi đang sử dụng VueJS CLI3 và NuxtJS ở đây và với Bootstrap4, nhưng nó sẽ hoạt động trên VueJS mà không cần NuxtJS:

<div
    class="dropdown ml-auto"
    :class="showDropdown ? null : 'show'">
    <a 
        href="#" 
        class="nav-link" 
        role="button" 
        id="dropdownMenuLink" 
        data-toggle="dropdown" 
        aria-haspopup="true" 
        aria-expanded="false"
        @click="showDropdown = !showDropdown"
        @blur="unfocused">
        <i class="fas fa-bars"></i>
    </a>
    <div 
        class="dropdown-menu dropdown-menu-right" 
        aria-labelledby="dropdownMenuLink"
        :class="showDropdown ? null : 'show'">
        <nuxt-link class="dropdown-item" to="/contact">Contact</nuxt-link>
        <nuxt-link class="dropdown-item" to="/faq">FAQ</nuxt-link>
    </div>
</div>
export default {
    data() {
        return {
            showDropdown: true
        }
    },
    methods: {
    unfocused() {
        this.showDropdown = !this.showDropdown;
    }
  }
}

0

Bạn có thể phát ra sự kiện javascript gốc tùy chỉnh từ một chỉ thị. Tạo một chỉ thị gửi một sự kiện từ nút, sử dụng node.dispatchEvent

let handleOutsideClick;
Vue.directive('out-click', {
    bind (el, binding, vnode) {

        handleOutsideClick = (e) => {
            e.stopPropagation()
            const handler = binding.value

            if (el.contains(e.target)) {
                el.dispatchEvent(new Event('out-click')) <-- HERE
            }
        }

        document.addEventListener('click', handleOutsideClick)
        document.addEventListener('touchstart', handleOutsideClick)
    },
    unbind () {
        document.removeEventListener('click', handleOutsideClick)
        document.removeEventListener('touchstart', handleOutsideClick)
    }
})

Cái nào có thể được sử dụng như thế này

h3( v-out-click @click="$emit('show')" @out-click="$emit('hide')" )

0

Tôi tạo một div ở cuối phần nội dung như vậy:

<div v-if="isPopup" class="outside" v-on:click="away()"></div>

.Outside là:

.outside {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0px;
  left: 0px;
}

Và away () là một phương thức trong Vue instance:

away() {
 this.isPopup = false;
}

Dễ dàng, hoạt động tốt.


0

Nếu bạn có một thành phần có nhiều phần tử bên trong phần tử gốc, bạn có thể sử dụng giải pháp It just works ™ này với boolean.

<template>
  <div @click="clickInside"></div>
<template>
<script>
export default {
  name: "MyComponent",
  methods: {
    clickInside() {
      this.inside = true;
      setTimeout(() => (this.inside = false), 0);
    },
    clickOutside() {
      if (this.inside) return;
      // handle outside state from here
    }
  },
  created() {
    this.__handlerRef__ = this.clickOutside.bind(this);
    document.body.addEventListener("click", this.__handlerRef__);
  },
  destroyed() {
    document.body.removeEventListener("click", this.__handlerRef__);
  },
};
</script>

0

Sử dụng gói này vue-click-external

Nó đơn giản và đáng tin cậy, hiện được nhiều gói khác sử dụng. Bạn cũng có thể giảm kích thước gói javascript của mình bằng cách chỉ gọi gói trong các thành phần bắt buộc (xem ví dụ bên dưới).

npm install vue-click-outside

Sử dụng :

<template>
  <div>
    <div v-click-outside="hide" @click="toggle">Toggle</div>
    <div v-show="opened">Popup item</div>
  </div>
</template>

<script>
import ClickOutside from 'vue-click-outside'

export default {
  data () {
    return {
      opened: false
    }
  },

  methods: {
    toggle () {
      this.opened = true
    },

    hide () {
      this.opened = false
    }
  },

  mounted () {
    // prevent click outside event with popupItem.
    this.popupItem = this.$el
  },

  // do not forget this section
  directives: {
    ClickOutside
  }
}
</script>


0

Bạn có thể tạo thành phần mới xử lý nhấp chuột bên ngoài

Vue.component('click-outside', {
  created: function () {
    document.body.addEventListener('click', (e) => {
       if (!this.$el.contains(e.target)) {
            this.$emit('clickOutside');
           
        })
  },
  template: `
    <template>
        <div>
            <slot/>
        </div>
    </template>
`
})

Và sử dụng thành phần này:

<template>
    <click-outside @clickOutside="console.log('Click outside Worked!')">
      <div> Your code...</div>
    </click-outside>
</template>

-1

thường thì mọi người muốn biết nếu người dùng rời khỏi thành phần gốc (hoạt động với bất kỳ thành phần cấp nào)

Vue({
  data: {},
  methods: {
    unfocused : function() {
      alert('good bye');
    }
  }
})
<template>
  <div tabindex="1" @blur="unfocused">Content inside</div>
</template>


-1

Tôi có một giải pháp để xử lý menu thả xuống chuyển đổi:

export default {
data() {
  return {
    dropdownOpen: false,
  }
},
methods: {
      showDropdown() {
        console.log('clicked...')
        this.dropdownOpen = !this.dropdownOpen
        // this will control show or hide the menu
        $(document).one('click.status', (e)=> {
          this.dropdownOpen = false
        })
      },
}

-1

Tôi đang sử dụng gói này: https://www.npmjs.com/package/vue-click-outside

Việc này ổn với tôi

HTML:

<div class="__card-content" v-click-outside="hide" v-if="cardContentVisible">
    <div class="card-header">
        <input class="subject-input" placeholder="Subject" name=""/>
    </div>
    <div class="card-body">
        <textarea class="conversation-textarea" placeholder="Start a conversation"></textarea>
    </div>
</div>

Mã tập lệnh của tôi:

import ClickOutside from 'vue-click-outside'
export default
{
    data(){
        return {
            cardContentVisible:false
        }
    },
    created()
    {
    },
    methods:
        {
            openCardContent()
            {
                this.cardContentVisible = true;
            }, hide () {
            this.cardContentVisible = false
                }
        },
    directives: {
            ClickOutside
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.