티스토리 뷰

Vue.JS

[Vue.JS] 사용자 정의 디렉티브

버미노트 2019. 2. 7. 23:07

1. 시작

기본 디렉티브 (v-model, v-show 등..) 외에도 사용자가 직접 정의한 디렉티브를 등록 할 수 있습니다. 기본적으로 Vue 2.0의 코드 재사용 및 추상화의 기본 형식은 컴포넌트 입니다. 하지만 일반 엘리먼트의 DOM에 접근이 필요한 경우 사용자 정의 디렉티브가 유용하게 사용 될 수 있습니다.

// 전역 사용자 정의 디렉티브 v-focus 등록
Vue.directive('focus', {
  // 바인딩 된 엘리먼트가 DOM에 삽입되었을 때...
  inserted: function (el) {
    // 엘리먼트에 포커스를 줍니다
    el.focus()
  }
})

위의 코드는 페이지가 로드되면 해달 엘리먼트에 포커스를 주는 디렉티브 입니다. (참고, 모바일 사파리에서도는 동작하지 않습니다.)

directives: {
  focus: {
    // 디렉티브 정의
    inserted: function (el) {
      el.focus()
    }
  }
}

디렉티브를 로컬로 등록하기 위해서는 컴포넌트의 옵션에 directives 옵션을 사용해야 합니다.

<input v-focus>

이렇게 정의 된 focus 디렉티브는 위의 코드와 같이 v-focus로 사용할 수 있습니다.

2. 훅 함수

디렉티브를 정의 할 때, 여러가지 훅 함수를 제공합니다. 훅 함수는 모두 선택사항입니다.

  • bind: 디렉티브가 처음 엘리먼트에 바인딩 될 때 한번만 호출됩니다. 이 훅 함수는 일회성 설정을 하는데 유용합니다.
  • inserted: 바인딩 된 엘리먼트가 부모 노드에 삽일 되었을 때 호출됩니다. 부모 노드 존재를 보장하며, 반드시 document 내에 있는 것은 아닙니다.
  • update: 디렉티브를 포함하는 컴포넌트의 VNode가 업데이트 되었을 때 호출됩니다. 그러나 자식이 업데이트 전일 가능성이 있습니다. 이 훅이 실행 되었을 때는 디렉티브의 값이 변경되었을 수도 변경되지 않았을 수도 있습니다. 디렉티브의 현재 값과 이전 값을 비교하여 불필요한 업데이트를 건너 뛸 수 있습니다. (VNode에 대해서는 다음 포스팅 할 render functions에서 이야기 할 것입니다.)
  • componentUpdated: 포함하고 있는 컴포넌트의 VNode, 그것들의 자식의 VNode가 업데이트 되었을 때 호출됩니다.
  • unbind: 디렉티브가 엘리먼트로부터 언바인딩 된 경우에만 한번 호출됩니다.

3. 디렉티브 훅 전달인자

디렉티브 훅은 전달 인자을 가집니다.

  • el: 디렉티브가 바인딩 되는 엘리먼트입니다. 이 인자를 통해 DOM을 조작할 수 있습니다.
  • binding: 아래의 속성들을 가진 객체입니다.
    • name: 디렉티브 이름, prefix(v-)가 없습니다.
    • value: 디렉티브에서 전달 받은 값, 예를 들면 v-my-directive="1+1"인 경우 value는 2입니다.
    • oldValue: 이전 값, updatecomponentUpdated에서만 사용할 수 있습니다. 이 값을 통해 디렉티브로 전달 받은 값이 변경 되었는지 확인 할 수 있습니다.
    • expression: 표현식 문자열, 예를 들면 v-my-directive="1+1"인 경우 expression"1+1"입니다.
    • arg: 디렉티브의 전달인자, 전달인자가 있는 경우에만 존재합니다. 예를 들면, v-my-directive:foo이면 "foo"가 됩니다.
    • modifiers: 디렉티브의 수식어 객체, 수식어가 있는 경우에만 존재합니다. 예를 들면, v-my-directive.foo.bar이면, 수식어 객체는 {foo: true, bar: true} 입니다.
  • vnode: Vue 컴파일러가 만든 가상 노드
  • oldVnode: 이전 가상 노드, updatecomponentUpdated에서만 사용할 수 있습니다.

el 뿐만 아니라 모든 전달인자는 readonly로 사용해야 합니다. 절대 변경하면 안됩니다. 훅을 통해 이 정보들을 전달해야 하는 경우 dataset를 사용하면 됩니다.

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
  bind: function (el, binding, vnode) {
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})

new Vue({
  el: '#hook-arguments-example',
  data: {
    message: 'hello!'
  }
})

디렉티브 사용 예제

4. 함수 약어

대부분의 경우 bindupdate에서 같은 동작을 할 때가 있습니다. 다른 훅은 신경쓰지 않고, bindupdate에서만 동작을 하는 약어를 제공합니다.

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

함수 약어 사용 예제

5. 객체 리터럴

디렉티브에 여러 값이 필요한 경우, JavaScript 객체를 전달 할 수 있습니다. 디렉티브에 JavaScript 표현식을 사용할 수 있습니다.

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

참고

'Vue.JS' 카테고리의 다른 글

[Vue.JS] 플러그인  (0) 2019.02.18
[Vue.JS] Render Functions & JSX  (0) 2019.02.14
[Vue.JS] Mixins  (0) 2019.02.05
[Vue.JS] 컴포넌트 (고급:Handling Edge Cases)  (0) 2019.02.02
[Vue.JS] 컴포넌트 (고급:Dynamic & Async Components)  (0) 2019.01.29
댓글
공지사항
최근에 올라온 글