Hello,
Looking for a simple way to implement functionality click-Outside in the element, I found this directive
. Besides, I couldn’t think of any other way than by directive.
Below is an adaptation of directive
for ES5
and a few more modifications.
Vue.directive('click-out', {
bind: function(element, binding, node) {
// verifica se o parametro da diretiva é diferente de um objeto do tipo function.
if(typeof binding.value !== 'function') {
var component = node.context.name;
var text = '[Vue-click-out:] a expressão informada deve ser uma função';
if(component) {
text += ' Component: ' + component;
};
console.warn(text);
};
// cria o evento e atribui ao elemento
var bubble = binding.modifiers.bubble;
var handler = function(evt) {
if(bubble || (!element.contains(evt.target) && element !== evt.target)) {
binding.value(evt);
};
};
element.__vueClickOutside__ = handler;
// adiciona o evento que trata os cliques fora do component
document.addEventListener('click', handler);
},
unbind: function(element) {
// remove o evento que trata cliques fora do componente
document.removeEventListener('click', element.__vueClickOutside__);
element.__vueClickOutside__ = null;
}
});
Implementation
Registering the above directive in your code, an example of usage will look like this:
Vue.directive('click-out', {
bind: function(element, binding, node) {
// verifica se o parametro da diretiva é diferente de um objeto do tipo function.
if (typeof binding.value !== 'function') {
var component = node.context.name;
var text = '[Vue-click-out:] a expressão informada deve ser uma função';
if (component) {
text += ' Component: ' + component;
};
console.warn(text);
};
// cria o evento e atribui ao elemento
var bubble = binding.modifiers.bubble;
var handler = function(evt) {
if (bubble || (!element.contains(evt.target) && element !== evt.target)) {
binding.value(evt);
};
};
element.__vueClickOutside__ = handler;
// adiciona o evento que trata os cliques fora do component
document.addEventListener('click', handler);
},
unbind: function(element) {
// remove o evento que trata cliques fora do componente
document.removeEventListener('click', element.__vueClickOutside__);
element.__vueClickOutside__ = null;
}
});
var navList = new Vue({
el: '#app',
data: function() {
return {
visible: false
}
},
methods: {
show: function() {
this.visible = !this.visible;
},
hide: function() {
this.visible = false;
}
}
})
.dropdown {
display: none;
}
.dropdown.active {
display: block;
}
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
<ul>
<li>Home</li>
<li @click="show" v-click-out="hide">
Products
<ul class="dropdown" :class="{active: visible}">
<li>Product 1</li>
<li>Product 2</li>
</ul>
</li>
<li>About us</li>
</ul>
</div>
Basically you have the v-bind
or :
for class
checking whether visible
is true (true
) and assigning the class .active
where appropriate. The v-on
or @
for the event click
, assigning by the method show
, true
or false
(the opposite of the current value in the property) visible
and the directive
v-click-out
, assigning by the method hide
, false
to visible
.
Testing
...<li @click="show" v-click-out="visible = true">...
In the case of this directive it is possible to only inform a method for execution, but you can adjust it to receive an expression from Vuejs.
Information
More about custom directives
(directives) in Vuejs 2.x here.