사용자 정의 리렉티브란
Vue 에서는 v-if, v-for, v-on, v-model등 다양한 디렉티브를 사용한다. 디렉티브가 하는 일을 프로그램의 관점에서 생각해 보면, 내부적으로 주어진 데이터에 따라 DOM을 조작하는 역할을 한다. 예를 들어 v-show는 값이 참이냐 거짓이냐에 따라 DOM 요소의 스타일에 display 프로퍼티 값을 수정한다.
그러나 때에 따라서는 Vue.js 내장 디렉티브 만으로는 구현할 수 없는 깊숙한 곳에 있는 요소에 대한 DOM 조작을 공통화 하고 싶다던가 DOM API를 호출하는 라이브러리를 Vue.js 애플리케이션에서 재사용 가능한 형태로 포함시키고 싶은 경우가 있다.
사용자 정의 디렉티브는 DOM 요소에 대한 저수준(low-level) 접근을 제공한다. 바꿔 말하면 DOC 요소를 조작해 동작을 원하는 대로 수정하거나 새로운 기능을 추가할 수 있게 해준다.
사용자 정의 디렉티브 정의하기
img 요소를 확장해서 이미지의 URL이 유효하지 않은 경우 대체 이미지로 폴백(fall-back)하는 디렉티브인 v-img-fallback을 만들어보자. HTML의 img요소에 이 사용자 정의 디렉티브를 적용해서 이미지를 받아오지 못한 경우의 로직을 추가한다.
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue app</title>
<script src="https://unpkg.com/vue@2.5.17"></script>
<script src="app.js"></script>
</head>
<body>
<div id="app">
<!-- src 속성값은 아까와 마찬가지로 존재하지 않는 URL이다 -->
<img v-fallback-image src="./logo.png" :alt="altText">
</div>
<script src="./app.js"></script>
</body>
</html>
app.js
Vue.directive('fallback-image', {
bind: function (el, binding) {
console.log('bind', binding)
el.addEventListener('error', function () {
el.src = 'https://dummyimage.com/400x400/000/ffffff.png&text=no+image'
})
},
update: function (el, binding) {
console.log('update', binding)
}
})
var vm = new Vue({
el: '#app',
data: function () {
return {
altText: 'logo'
}
}
})
테스트 결과
위 소스들과 같은 폴더에 logo.png파일을 두고 브라우저로 index.html을 실행하면 img 랜더링이 정상적으로 되어서 logo.png파일이 화면에 출력된다.
여기서 logo.png의 이름을 다른 이름으로 바꾸고 index.html을 실행해보면 img 태그 렌더링시 error가 발생하고 걸어 두었던 v-fallback-image 디렉티브에 지정한 bind 함수에 의해 실패 시 지정한 이미지가 출력되게 된다.
스크립트 내용
전역 디렉티브를 등록하려면 Vue.directive라는 API를 사용한다. 이 API의 첫번째 인자는 디렉티브의 이름이고, 두 번째 인자는 동작을 정의하는 디렉티브 정의 객체다.
Vue.directive('fallback-image',
// 두 번째 인자는 동작을 정의하는 디렉티브 정의 객체. 아래는 bind, update 훅 함수에 대한 정의가 되어 있다.
{
bind: function (el, binding) {
console.log('bind', binding)
el.addEventListener('error', function () {
el.src = 'https://dummyimage.com/400x400/000/ffffff.png&text=no+image'
})
},
update: function (el, binding) {
console.log('update', binding)
}
}
)
훅이름 | 내용 |
bind | 디렉티브가 대상 요소와 연결됬을 때 단 한 번 호출됨. |
inserted | 연결된 요소가 부모 요소에 삽입되는 시점에 호출됨(부모 요소의 존재는 보장되나, 요소가 문서에 포함되는지는 보장되지 않음) |
update | 디렉티브 값의 변화 등에 따라 연결된 요소를 포함하는 컴포넌트의 VNode가 수정될 때 호출됨. 디렉티브 값이 변화하지 않아도 호출될 수 있으므로 값의 이전값과 비교해 불필요한 호출을 방지한다. |
componentUpdated | 컴포넌트의 VNode와 자식 컴포넌트의 VNode가 수정됬을 때 호출됨. |
unbind | 디렉티브가 연결된 요소와 분리됬을 때 단 한 번 호출됨. bind로 등록한 이벤트 리스너 삭제 등 뒷정리를 목적으로 사용한다. |
'Frontend Development > Vue.js' 카테고리의 다른 글
[Vue.js] webpack.config.js 분석 (0) | 2022.03.16 |
---|---|
[Vue.js] Storybook custom webpack, preview 추가 (0) | 2022.02.21 |
[Vue.js] Karma로 Unit 테스트 시 특정 폴더 제외 하기 (0) | 2022.02.14 |
[Vue.js] vue 용 Storyboard 설치하기 (0) | 2022.02.14 |
[Vue.js] karma로 unit 테스트 시 Can't find variable: WeakMap 에러 해결 (0) | 2022.02.12 |