본문 바로가기

JavaScript/Vue.js

[Vue.js] Vue 디렉티브(Directives)

Vue의 데이터 바인딩에 대해서 알아보면서 v-bind라는 것도 알게 됐다.

정식 명칭은 디렉티브(Directives) 라고 한다.

번역하자면 지시문이고, HTML 태그 내의 속성으로 선언된다.

단순하게 'v-로 시작되는 속성을 가진 HTML 태그에 지시를 내린다'라고 생각하면 되겠다!

 

기본적으로 제공하는 디렉티브에 대해서 정리해봐야겠다.

 

  • v-text
  • v-html
  • v-show
  • v-if / v-else / v-else-if
  • v-for
  • v-on
  • v-bind
  • v-model
  • v-slot
  • v-pre
  • v-cloak
  • v-once
  • v-is

15개나 있어서 간단하게나마 정리해봐야겠다.

1. v-text

 

<div id="app" v-text="txt"></div>

 

new Vue({
    el: '#app',
    data: {
    	txt: 'abcd'
    }
});

 

엘리먼트의 textContent를 업데이트한다.
텍스트의 일부 수정이 있을 경우에는 Mustache Tag(이중 중괄호 문법) 를 활용해야 한다.

2. v-html

 

<div id="app" v-html="html"></div>

 

new Vue({
    el: '#app',
    data: {
    	html: '<p>Hi</p>'
    }
});

 

엘리먼트의 innerHTML을 업데이트한다.

하지만 공식 홈페이지의 설명으로는 가급적 사용을 권장하지 않는 것 같다.

그 이유는 웹사이트에서 임의의 HTML을 동적으로 렌더링 하면 XSS 공격에 취약할 수 있기 때문이라고 한다.

v-html 디렉티브는 머릿속에서 지우는 걸로 해야겠다.

3. v-show

 

<div id="app" v-show="show">Hello</div>

 

new Vue({
    el: '#app',
    data: {
    	show: false
    }
});

 

v-show는 표현식 값의 참-거짓을 기반으로 엘리먼트의 display CSS 속성을 전환한다.

표현식이 true면 보여주고 false면 숨긴다.

특징은 v-show를 사용한 엘리먼트는 DOM에 항상 렌더링은 되어 남아있고 display 속성만 변경한다는 점이다.

또한, v-show는 <template> 엘리먼트를 지원하지 않으며, v-else와 함께 쓸 수 없다고 한다.

화면에 숨겼다가 보여주는 작업이 있으면 자주 쓰일 것 같은 디렉티브이다.

4. v-if / v-else / v-else-if

<div id="app">
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
</div>

 

new Vue({
    el: '#app',
    data: {
    	type: 'A'
    }
});

 

v-if는 표현식 값의 참-거짓에 따라 엘리먼트를 조건부로 렌더링 한다.

특징은 엘리먼트와 포함된 디렉티브/컴포넌트는 전환되는 동안 파괴되고 재구성되는 점이다.

엘리먼트가 <template> 엘리먼트인 경우 해당 컨텐츠가 조건부 블록으로 추출된다고 한다.

v-show와 다른 점은 렌더링의 차이와 <template> 지원 여부 일 것 같다.

또한, v-for와 함께 사용할 경우 v-if보다 v-for 우선순위가 높다고 한다.

 

v-else-if는 v-if 엘리먼트나 v-else-if 엘리먼트 바로 뒤에 있어야 인식이 되고

v-else는 v-if 엘리먼트와 v-else-if 엘리먼트 바로 뒤에 있어야 인식이 된다.

5. v-for

<div id="app">
    <div v-for="item in items">
        {{ item.text }}
    </div>
</div>

 

new Vue({
    el: '#app',
    data: {
        items: [{ text: 'Foo' }, { text: 'Bar' }]
    }
});

 

v-for는 원본 데이터를 기준으로 엘리먼트 또는 템플릿 블록을 여러 번 렌더링 한다.

디렉티브의 값은 반복되는 현재 엘리먼트의 별칭을 제공하기 위해 특수 구문인 alias in expression 을 사용해야 한다.

또는, 아래와 같이 인덱스의 별칭(객체일 경우 키)을 지정할 수도 있다.

 

<div v-for="(item, index) in items"></div>
<div v-for="(value, key) in object"></div>
<div v-for="(value, name, index) in object"></div>

 

<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>

 

배열과 객체를 별칭으로 자유롭게 반복적인 렌더링 작업을 할 수 있어서 v-for는 많이 쓰일 것 같다.

그리고 v-for에는 key라는 속성이 있는데 의도적인 경우를 제외하고는 언제나 key를 추가하는 것을 권장한다고 한다.

key 속성은 Vue가 노드를 식별할 수 있는 힌트로 사용되고 재정렬할 때 기준이 된다.

6. v-on

<!-- 메서드 핸들러 -->
<button v-on:click="doThis"></button>

<!-- 동적 이벤트 -->
<button v-on:[event]="doThis"></button>

<!-- 약칭 -->
<button @click="doThis"></button>

<!-- 자식컴포넌트 이벤트 수신 -->
<my-component @my-event="handleThis"></my-component>

 

v-on은 엘리먼트에 이벤트 리스너를 연결해준다.

동적으로 이벤트를 전달할 수도 있고 약칭 '@' 으로 표현할 수도 있다.

특징으로는 커스텀 엘리먼트 컴포넌트에서 사용될 경우 자식 컴포넌트에서 전달한 이벤트를 수신할 수 있다.

다양한 예제가 있겠지만 대표적인 예제만 알아보았다.

웹에서 이벤트 연결은 필수이므로 자주 쓰일 수밖에 없는 디렉티브 일 것이다.

7. v-bind

<!-- 속성 바인드 -->
<img v-bind:src="imageSrc" />

<!-- 동적 속성 이름 -->
<button v-bind:[key]="value"></button>

<!-- 약어 -->
<img :src="imageSrc" />

<!-- 자식컴포넌트로 데이터 전달 -->
<my-component :props="someThing"></my-component>

 

v-bind는 엘리먼트 속성을 바인딩할 수 있다.

속성은 동적으로도 전달이 가능하며 약칭 ':' 으로 표현할 수도 있다.

특징으로는 props 속성을 통해 데이터 바인딩하여 자식 컴포넌트로 전달이 가능하다.

v-on과 마찬가지로 자주 쓰일 수밖에 없는 디렉티브일 것이다.

8. v-model

<input v-model="message" placeholder="edit me" />
<p>메시지: {{ message }}</p>

 

v-model은 폼 입력 엘리먼트 또는 컴포넌트에 양방향 바인딩을 생성해준다.

폼 입력 엘리먼트는 input, select, textarea가 있고, 주로 input 태그와 함께 사용할 것 같다.

 

<!--
.lazy - input 대신에 change 이벤트를 수신
.number - 유효한 입력 문자열을 숫자로 캐스팅
.trim - 입력값을 트림(trim)처리
-->

<input v-model.lazy="msg" />
<input v-model.number="age" type="number" />
<input v-model.trim="msg" />

 

v-model의 특징은 위와 같은 수식어를 추가하여 유용한 기능을 사용할 수 있다는 점이다.

입력받는 곳이 많다면 자주 쓰일 것 같은 디렉티브이다.

9. v-slot

<todo-button>
  Add todo
</todo-button>

<!-- todo-button 컴포넌트 템플릿 -->
<button class="btn-primary">
  <slot></slot>
</button>

<!-- HTML 렌더링 -->
<button class="btn-primary">
  Add todo
</button>

 

간단한 문자열 slot에 대한 예제이다.

만약 <todo-button> 컴포넌트의 템플릿이 <slot> 코드를 가지고 있지 않다면, 태그 내부에 위치한 모든 컨텐츠는 무시된다.

slot을 활용한다면 컴포넌트 내부의 컨텐츠를 전달하여 화면에 렌더링 할 수 있다.

 

<!-- 이름있는 슬롯(Named slots) -->
<base-layout>
  <template v-slot:header>
    Header content
  </template>

  <template v-slot:default>
    Default slot content
  </template>

  <template v-slot:footer>
    Footer content
  </template>
</base-layout>

<!-- base-layout 컴포넌트 -->
<div class="container">
  <header>
    <slot name="header">
  </header>
  <main>
    <slot>
  </main>
  <footer>
    <slot name="footer">
  </footer>
</div>

<!-- HTML 렌더링 -->
<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

 

v-slot은 이름이 있는 slot에 컨텐츠를 제공하기 위해 template 엘리먼트의 지시자로 사용된다.

약어로는 '#'을 사용하고 컴포넌트에 대한 이해와 사용도가 많으면 유용하게 사용할 수 있는 디렉티브일 것 같다.

10. v-pre

<span v-pre>{{ this will not be compiled }}</span>

 

v-pre는 다른 표현식 없이 사용되고

이 엘리먼트와 모든 하위 엘리먼트에 대한 컴파일을 건너뛴다고 한다.

 

원시 mustache 태그를 표시하는 데 사용할 수 있고

디렉티브가 없는 많은 노드를 건너뛰면 컴파일 속도가 빨라질 수 있다고 한다.

특별한 표현 없이 문자열만 있다거나 하는 곳에 사용하면 좋을 디렉티브인 것 같다.

11. v-cloak

[v-cloak] {
  display: none;
}

 

<div v-cloak>
  {{ message }}
</div>

 

v-cloak은 연결된 컴포넌트 인스턴스가 컴파일을 완료할 때까지 엘리먼트에 남아있다고 한다.

CSS 규칙과 함께 작성된 v-cloak은 컴포넌트 인스턴스가 준비될 때까지

컴파일되지 않은 mustache 바인딩을 숨기는 데 사용할 수 있다.

 

위 예제의 div 태그는 컴파일이 완료될 때까지 화면에 표시되지 않는다.

12. v-once

<!-- 단일 엘리먼트 -->
<span v-once>This will never change: {{msg}}</span>

<!-- 엘리먼트가 자식 엘리먼트를 가진 경우 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>

<!-- 컴포넌트 -->
<my-component v-once :comment="msg"></my-component>

<!-- v-for 디렉티브 -->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

 

v-once를 사용한 엘리먼트와 컴포넌트는 한번(once)만 렌더링 된다.

이후에 재 렌더링 할 때는 엘리먼트, 컴포넌트, 모든 하위 엘리먼트는 정적 컨텐츠로 처리되고 건너뛰는 특징이 있다.

그러므로 업데이트 성능을 최적화하는 데 사용할 수 있을 것이다.

13. v-is

<!-- currentTabComponent가 변하면 컴포넌트가 바뀝니다.  -->
<component :is="currentTabComponent"></component>


v-is는 3.1.0 버전 이후부터 더 이상 사용되지 않는다고 한다.

그 대신 is 속성을 사용하라고 설명되어있다.

is 속성을 통해서 동적으로 변하는 컴포넌트를 만들 수 있다.

 


 

기본적인 디렉티브이지만 중요한 부분도 많아서 하나씩 정리해보았다.

헷갈릴 때 한 번씩 찾아보면 좋을 것 같다!

 

'JavaScript > Vue.js' 카테고리의 다른 글

[Vue.js] 컴포넌트 통신(props, event emit)  (0) 2022.08.29
[Vue.js] 데이터 바인딩(data binding)  (0) 2022.08.21
[Vue.js] Vue 시작하기  (0) 2022.08.21