[Vue.js] Custom Directive : Outside Click Event
| `Custom Directive`๋? ๐ itinerant.tistory.com/181
Custom Directive๋ฅผ ์ด์ฉํด์, ๋๋ ํฐ๋ธ๋ฅผ ๊ฐ๊ณ ์๋ ์๋ฆฌ๋จผํธ ๋ฐ๊นฅ(์ธ) ๋ถ๋ถ์ ํด๋ฆญํ ๊ฒฝ์ฐ๋ฅผ ๊ฐ์งํ๋ ์ด๋ฒคํธ๋ฅผ ๋ง๋ค์ด ๋ณด๊ณ ์ ํ๋ค.
1. ์๋ฆฌ
โ๏ธ ๋ฐ๊นฅ ๋ถ๋ถ์ ์ ํํ๋์ง ๊ฐ์งํ๊ธฐ ์ํด์๋ Body ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํด์ ํ์ฌ ํด๋ฆญํ ํ๊ฒ์ด ํด๋น ์๋ฆฌ๋จผํธ์ธ์ง ์ฒดํฌํ๋ ๋ฐฉ์์ผ๋ก ์ฝ๊ฒ ๋ง๋ค ์ ์๋ค.
2. ์์
1. ๊ฐ์ฅ ๋จผ์ , bind ๋ฅผ ์ด์ฉํด์ ์ฒ์ ์๋ฆฌ๋จผํธ์ ๋ฐ์ธ๋ฉ ๋ ๋ ์คํํ ๊ฒ์ ์ ์ธํด ์ค๋ค.
{
bind: function (el, binding, vnode) {
// ...
},
}
2. ์ฐ๋ฆฌ๋ ๋๋ ํฐ๋ธ๋ฅผ ๊ฐ๋ ์๋ฆฌ๋จผํธ ์ธ์ ๋ถ๋ถ์ ์ด๋ฒคํธ๋ฅผ ๊ฑธ์ด์ค ๊ฒ์ด๋ฏ๋ก
๋ฐ๋์ ํด๋ฆญ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฐ๊ฒฐํด์ ๋ชจ๋ ํด๋ฆญ์ ๊ฐ์งํ๋๋ก ํ๋ค.
{
bind: function (el, binding, vnode) {
document.body.addEventListener('click', [์คํํ _ํจ์]);
},
}
3. ๊ทธ ๋ค์, ํด๋ฆญ์ด๋ฒคํธ ํ๊ฒ์ด ๋๋ ํฐ๋ธ์ ์ฐ๋๋ ์๋ฆฌ๋จผํธ๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ํ๋ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ํจ์๋ฅผ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค.
{
bind: function (el, binding, vnode) {
el.eventClickOutside = function (event) {
if (!(el == event.target || el.contains(event.target))) {
// ... do something ...
}
};
},
}
์ ์ฒด ์ฝ๋
{
bind: function (el, binding, vnode) {
// create event
el.eventClickOutside = function (event) {
// when target is not element or is not element childs
if (!(el == event.target || el.contains(event.target))) {
// ... do something ...
}
};
// event binding
document.body.addEventListener('click', el.eventClickOutside);
},
unbind: function (el) {
document.body.removeEventListener('click', el.eventClickOutside);
},
}
3. ์คํ ์ฝ๋(์์)
// example.vue
<template>
<div id="app">
<button @click.stop="openMenu">open menu</button>
<div id="menu" v-show="show" v-click-outside:openMenu="false">
<a herf="#">1. Apple</a>
<a herf="#">2. Banana</a>
<a herf="#">3. Carrot</a>
</div>
</div>
</template>
<script>
export default {
data() {
return {
show: false,
};
},
directives: {
'click-outside': {
bind: function (el, binding, vnode) {
// create event
el.eventClickOutside = function (event) {
// when target is not element or is not element childs
if (!(el == event.target || el.contains(event.target))) {
// call function
vnode.context[binding.arg](binding.value);
}
};
// event binding
document.body.addEventListener('click', el.eventClickOutside);
},
unbind: function (el) {
document.body.removeEventListener('click', el.eventClickOutside);
},
},
},
methods: {
openMenu(value) {
if (typeof value === 'boolean') this.show = value;
else {
this.show = !this.show;
}
}
}
};
</script>
<style>
button {
background-color: #334867;
color: white;
border: 1px solid #334867;
border-radius: 5px;
padding: 4px 10px;
font-size: 20px;
}
#menu {
background-color: skyblue;
width: fit-content;
margin-top: 5px;
padding: 4px 28px;
display: flex;
flex-direction: column;
}
a {
cursor: pointer;
font-weight: 800;
font-size: 14px;
color: white;
padding: 4px 0px;
}
</style>
'WEB > Vue.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Vue.js] Eslint + Prettier ์ค๋ฅ (โยทยทยทยทยทยทยท) (0) | 2021.05.26 |
---|---|
[Vue.js] Vue์์ JQuery ์ฌ์ฉํ๊ธฐ (0) | 2021.01.16 |
[Vue.js] Custom Directive (0) | 2021.01.13 |
[Vuejs][VScode] 'v-slot' directive doesn't support any modifier. (0) | 2020.12.10 |
[Vuejs] v-html (0) | 2020.12.04 |