
Vue에서 지원하는 디렉티브 뿐만 아니라 개발자가 원하는 기능이 들어간 디렉티브를 만들 수 있습니다.
커스텀 디렉티브 미리보기
커스텀 디렉티브 (Custom Directive)
Vue는 디렉티브(Directive)를 통해 이벤트처리를 하거나 조건에 따라 렌더링하는 등 다양한 기능을 제공합니다. 기본적으로 제공하는 디렉티브 대신 원하는 기능이 들어간 디렉티브를 만들 수 있습니다. 예를 들어 v-lazy라는 플러그인이 있습니다.
<ul>
<li v-for="img in list">
<!-- 이미지를 lazy load 합니다. -->
<img v-lazy="img.src" >
</li>
</ul>
v-lazy
라는 커스텀 디렉티브를 통해 이미지를 lazy load합니다. 이렇게 자주 사용하는 기능들을 다시 사용하기 편하게 만들어주는 게 커스텀 디렉티브 역할입니다.
재사용성 높이는 방법들
디렉티브 뿐만 아니라 재사용성을 높이는 방법들이 있습니다. 바로 컴포넌트(Component)와 컴포저블(Composable)입니다. 이 둘과 같이 비교해보자면
컴포넌트(Component)
: UI와 기능, 스타일 들을 블록처럼 만들어 사용하는데 목적을 둡니다.컴포저블(Composable)
: 상태를 가진 로직(stateful logic)을 재활용하는데 목적을 둡니다.커스텀 디렉티브(Custom Directive)
: 컴포넌트가 아닌 기본 태그들에 접근해서 처리하는 로직을 재활용하는데 목적을 둡니다.그래서 만약 간단하게 DOM에 접근해서 조작하는 정도라면 커스텀 디렉티브를 사용하는 방법을 추천합니다. 위에서 다룬 v-lazy
가 좋은 예시입니다.
커스텀 디렉티브 등록하기
커스텀 디렉티브를 등록하는 방법은 두 가지가 있습니다.
전역으로 등록하기
Vue App의 directive
함수를 사용합니다.
const app = createApp({});
// 모든 컴포넌트에서 v-focus를 사용 가능
app.directive('focus', {
// ...
});
로컬로 등록하기
컴포넌트의 directives
속성을 사용합니다.
export default {
// 이 컴포넌트 내에서만 v-focus 사용 가능
directives: {
focus: {
// ...
}
}
}
디렉티브 훅(Hook)
컴포넌트처럼 디렉티브도 고유한 훅(Hook) 함수가 존재합니다. 훅 함수는 특정 상황이 되었을 때 호출되는 함수입니다.
created
: 태그 속성이 붙거나(bound) 이벤트 리스너가 적용되기 전에 호출됩니다.beforeMount
: DOM에 태그가 삽입되기 전에 호출됩니다.mounted
: 자식들이 모두 마운트되고 부모 컴포넌트에 바운드되면 호출합니다.beforeUpdate
: 부모 컴포넌트가 업데이트 되기전에 호출됩니다. updated
: 부모 컴포넌트와 자식들이 모두 업데이트 되고 호출됩니다.beforeUnmount
: 부모 커모넌트가 마운트 해제되기 전에 호출됩니다.unmounted
: 부모 컴포넌트가 호출 해제되면 호출됩니다. app.directive(name, {
created(el, binding, vnode, prevVnode) {
binding.instance.logs.push("created");
},
beforeMount(el, binding, vnode, prevVnode) {
binding.instance.logs.push("beforeMount");
},
mounted(el, binding, vnode, prevVnode) {
binding.instance.logs.push("mounted");
}
beforeUpdate(el, binding, vnode, prevVnode) {
binding.instance.logs.push("beforeUpdate");
},
updated(el, binding, vnode, prevVnode) {
binding.instance.logs.push("updated");
},
beforeUnmount(el, binding, vnode, prevVnode) {
binding.instance.logs.push("beforeUnmount");
},
unmounted(el, binding, vnode, prevVnode) {
binding.instance.logs.push("unmount");
}
});
훅 함수 전달 인자
해당 훅 함수를 사용한다면 같이 오는 전달 인자들이 있습니다.
el
: 디렉티브를 넣은 태그가 들어있습니다. 만약 <div v-my-directive></div>
라면
binding
: 다음 속성들이 들어있는 객체입니다.value
: 디렉티브에 넣은 값이 들어있습니다. 예를 들어 v-my-directive="1 + 1"라면, 2가 들어있습니다.oldValue
: 이전 값. 값이 변경되지 않더라도 사용가능합니다.arg
: directive에 전달된 인자가 들어있습니다. v-my-directive:foo라면 foo값이 들어있습니다.modifiers
: 수식어. v-my-directive.foo.bar라면 { foo: true, bar: true }가 들어있습니다.instance
: 디렉티브가 들어간 컴포넌트의 인스턴스가 들어있습니다.dir
: 디렉티브 정의 객체
vnode
: 해당 태그의 VNode가 들어있습니다.
prevVnode
: 해당 태그의 이전 VNode가 들어있습니다. el
값을 제외하고는 모두 읽는 용도로만 사용하고 수정하면 안됩니다. hook에서 데이터를 공유해야한다면 태그의 dataset을 사용해주세요.(data-…)
훅 함수 약식
mounted
와 updated
는 동일한 동작을 하도록 하는 경우가 많습니다. 그러다보니 이를 줄여서 사용할 수도 있는데요.
<div v-color="color"></div>
객체가 아닌 함수로 바로 넣을 경우 해당 함수는 mounted
와 updated
때마다 호출됩니다.
app.directive('color', (el, binding) => {
el.style.color = binding.value
})
컴포넌트에 사용하는 경우
컴포넌트를 사용하는 경우 컴포넌트의 최상단 태그에 자동적으로 들어갑니다. 하지만 Vue 3부터는 여러 태그가 들어갈 수 있게 되었습니다. 그런 경우 경고가 나타나면서 무시됩니다. 속성처럼 v-bind="$attrs"
방식으로 전달할 수 없기 때문에 컴포넌트에 커스텀 디렉티브를 사용하는 것은 권장하지 않습니다.