You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/v2/cookbook/clickoutside-directive.md
+42-25Lines changed: 42 additions & 25 deletions
Original file line number
Diff line number
Diff line change
@@ -6,18 +6,20 @@ order: 2.1
6
6
7
7
## What we are building
8
8
9
-
Many UI elements require to have to clicks that happen outside of them. Common usecases are:
9
+
Many UI elements need to react to clicks that happen *outside* of them. Common usecases are:
10
10
11
11
* Modals
12
12
* Dropdown menus
13
13
* Popovers
14
14
* Image Lightboxes
15
15
16
-
We will build a small [Custom Directive](https://vuejs.org/v2/guide/custom-directive.html) that we can use in any component that needs this behaviour. One such component is the [modal example](https://vuejs.org/v2/examples/modal.html) from the Vue.js Website, so we will use this as a base component to demonstrate the usage of our new custom directive.
16
+
We will build a small [Custom Directive](https://vuejs.org/v2/guide/custom-directive.html) that we can use in any component in need of this behaviour. One such component is the [modal example](https://vuejs.org/v2/examples/modal.html) from the Vue.js website, so we will use this as a base component to demonstrate the usage of our new directive.
17
17
18
-
The result will look like this:
18
+
> If you haven't already read the our Vue.js Guide about custom directives, we recommend you change this now. [Click here](../guide/custom-directive.html) to got to the relevant section in the guide.
19
19
20
-
```html
20
+
Ready? Great. So this is what the endresult of our efforts will look like:
21
+
22
+
```html
21
23
<modalv-clickoutside="handler">
22
24
<!--
23
25
"handler" should be a method in your component.
@@ -26,36 +28,46 @@ The result will look like this:
26
28
</modal>
27
29
```
28
30
29
-
## Starting simple
31
+
## bind(): Adding the desired behavior
30
32
31
-
The basic functionality is easy enough to achive. We register a new directive with Vue, and use
32
-
the `bind()` hook to register an event listener on the document:
33
+
The basic functionality is easy enough to achive. We register a new directive with Vue, and use the `bind()` hook to register an event listener on the document:
33
34
34
-
```JavaScript
35
+
```javascript
35
36
Vue.directive('clickoutside', {
36
37
bind(el, binding) {
37
-
consthandler=binding.value// this gives us the "handler" function the component passed to the directive.
So what happened here? When the directive is bound to the element we defined it on, its `bind()` hook is called.
49
-
50
-
In this hook, we add an Event listener to the document, which will call the handler of the component on click.
59
+
So what happened here?
51
60
52
-
And to make sure that this handler is only called when the click actually happened outside of out element `el`, we first weither the event's target was `el` or one of its child nodes.
61
+
* When the directive is bound to the element, its `bind()` hook is called.
62
+
* In this hook, we add an Event listener to the document, which will call the handler of the component for *any* click happening on our page.
63
+
* We use `setTimeout()` because if we didn't, then a `click` event from a button that is responsible to make our modal appear could trigger our directive's handler immediatly, and we don't want that, of course.
64
+
* And to make sure that this handler is only called when the click actually happened outside of out element `el`, we first check that the event's target wasn't `el` or one of its child nodes.
53
65
54
-
## Cleaning up after ourselves: Removing the Listener
66
+
## unbind(): Cleaning up after ourselves
55
67
56
-
Our directive does the job, but it still has a flaw: We have no mechanism in place to remove the listener again if `el` is removed from the DOM. This is problematic because the usual usecase of our directive on a `<modal>`will be to close a modal, for example, so the listener should be gone after that, too.
68
+
Our directive does the job, but it still has a flaw: We have no mechanism in place to remove the listener again if `el` is removed from the DOM. This is problematic because the usual usecase of our directive on a `<modal>`will be to close a modal, for example, so our directive will be gone after this too - and so should the listener.
57
69
58
-
We can correct that with the `unbind()` hook, but there's a catch we have to work around: since directives don't have instances, we can't save the handler method on it. To solve this challenge, we have two possibilities: we can either cache the hander on the element, or we can use a ES6 [Map](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Map). Using the latter is much cleaner, but requires a polyfill for older browsers. We will show you both ways here.
70
+
We can correct that with the `unbind()` hook, but there's a catch we have to work around: since directives don't have instances, we can't save the handler method on it. To solve this challenge, we have two possibilities: we can either cache the hander on the element, or we can use a ES6 [Map](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Map). Using the latter is much cleaner because we don't have to touch the element, but requires a polyfill for older browsers. We will show you both ways here.
0 commit comments