Back Ground

Vue - Directive(지시문) 본문

Javascript/Vue.js

Vue - Directive(지시문)

Back 2019. 3. 13. 16:02

디렉티브(Directive)


그대로 번역하면 지시문을 뜻한다.

Vue엘리먼트에서 사용되는 특별한 속성이다.

기능상에서 가장 중요한 역할인 엘리먼트에게 ~~하게 작동하라 하고 지시를 해주는 지시문인거다.



- 소개

디렉티브는 Vue의 기능들을 사용하기 위해서 사용하는

HTML태그안에 들어가는 하나의 속성이다.

디렉티브는 여러종류가 있는데

모두 v-text 이런식으로  'v-' 라는 앞글자를 지니고 있다.



- 종류

디렉티브는 현재 13개의 종류가 있다.  참고 

  1. v-text
  2. v-html
  3. v-show
  4. v-if
  5. v-else
  6. v-else-if
  7. v-for
  8. v-on
  9. v-bind
  10. v-model
  11. v-pre
  12. v-cloak
  13. v-once





- 사용


1) v-text 디렉티브


1
<h1>{{ name }}</h1>
cs


이것과 같은 기능을 {{ }}을 사용하는 대신 v-text라는 디렉티브를 사용하여 구현해본다.


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello 
      <span v-text="name"></span>
    </h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


span태그에 디렉티브를 사용하여 내부의 값 Vue엘리먼트의 name변수로 설정 되게했다.



JS

1
2
3
4
5
6
7
8
// 새로운 뷰를 정의합니다
var app = new Vue({
  el: '#app'// 어떤 엘리먼트에 적용을 할 지 정합니다
  // data 는 해당 뷰에서 사용할 정보를 지닙니다
  data: {
    name'<i>이탈릭</i>'
  }   
});
cs


이렇게 하면 


v-text에 지정한 name변수에 data.name가 바인딩되기 때문에

 Hello <i>이탈릭</i>

이라는 결과가 나올 것이다.












2) v-html 디렉티브


HTML으 기본적으로 텍스트형태로만 렌더링되게 해주기 때문에 태그를 막고,

또 XSS같은것도 차단하기에 유용하다.



XSS란

사이트 간 스크립팅은 웹 애플리케이션에서 많이 나타나는 취약점의 하나로 

웹사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점


출처 : https://ko.wikipedia.org/wiki/%EC%82%AC%EC%9D%B4%ED%8A%B8_%EA%B0%84_%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8C%85 


하지만 가끔씩은 html 랜더링해야 할 때도 있다.

그럴때 "여기서 렌더링 할건 html 형식이다."라는걸 지정하기 위해 v-html을 사용한다.





HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello 
      <span v-html="name"></span>
    </h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs

이렇게 v-text가 아닌 v-html을 넣어주면 


결과

Hello 이탈릭 

이렇게 html태그가 들어간 형태가 된다.




React에선

 dangerouslySetInnerHTML란걸 사용하는거랑 비슷하다.




v-html을 사용하는 경우엔, [꼭 명심]

- 서버측에서 불필요한 부분을 필터링하게 할 것!

잘못하면 XSS나 불 필요한 악성태그가 렌더링 될수 있다.












3) v-show 디렉티브


이 디렉티브는 이름만 보고도 살짝 유추 할 수 있다.

해당 엘리먼트가 보여질지,

보여지지 않을지 true/false값을 지정할 수 있다.


자바스크립트의 data부분에 다음과 같이 visivle이란 변수를 넣었다.


JS

1
2
3
4
5
6
7
8
9
// 새로운 뷰를 정의합니다
var app = new Vue({
  el: '#app'// 어떤 엘리먼트에 적용을 할 지 정합니다
  // data 는 해당 뷰에서 사용할 정보를 지닙니다
  data: {
    name'<i>이탈릭</i>',
    visible: true
  }   
});
cs


이제 html에서 v-show값을 우리가 만든 변수명, visible로 설정하겠다.



HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello 
      <span v-show="visible" v-html="name"></span>
    </h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs



화면을 보면 달라진게 없지만 

console을 열어서 app.visible = false 라고 입력하면
사라지고 app.visible = true 라고 입력하면 나타난다.


벨로퍼트 결과창 이미지












4) v-if 디렉티브


v-if디렉티브는 변수명 대신 조건문을 쓴다.


JS

1
2
3
4
5
6
7
8
// 새로운 뷰를 정의합니다
var app = new Vue({
  el: '#app'// 어떤 엘리먼트에 적용을 할 지 정합니다
  // data 는 해당 뷰에서 사용할 정보를 지닙니다
  data: {
    value: 0
  }   
});
cs


한번 v-if를 사용하여,

값 5 이상일때만 보이도록 설정해본다.

해당 디렉티브의 값에 ""로 감싸준 후  조건문을 넣어주면 된다.


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1 v-if="value > 5">value 가 5보다 크군요</h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


렌더링된 화면을 보면 아무것도 안나올 것이다. 

한번 콘솔에서 app.value = 6 이렇게 값을 5보다 큰 값으로 설정하면


벨로퍼트 결과창 이미지












5) v-else 디렉티브


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1 v-if="value > 5">value 가 5보다 크군요</h1>
    <h1 v-else>value 가  5 보다 작아요</h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs



결과

벨로퍼트 결과창 이미지











6) v-else-if 디렉티브


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1 v-if="value > 5">value 가 5보다 크군요</h1>
    <h1 v-else-if="value === 5">값이 5네요</h1>
    <h1 v-else>value 가  5보다 작아요</h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


이렇게 else if를 사용하면 된다.









7) v-pre 디렉티브


이 디렉티브는 특정 엘리먼트를 무시하는데 사용한다.

이걸 사용하므로서, 

Vue 시스템에서 해당 엘리먼트는 지시문이 없다는걸 

인식하게 되어 그 엘리먼트 내부의 자식엘리먼트들을 신경쓰지 않고 그냥 건너뜁다. 

이렇게 함으로써, 컴파일 속도가 빨라집니다.



이 디렉티브를 사용하면 {{ }} 이런 머스태쉬 태그를 그대로 표시 할 수 있다.

(생긴게 수염 같다고해서 머스태쉬라고 부릅니다)



HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1 v-if="value > 5">value 가 5보다 크군요</h1>
    <h1 v-else-if="value === 5">값이 5네요</h1>
    <h1 v-else>value 가  5보다 작아요</h1>
    <h1 v-pre>{{ 이건 그대로 렌더링해줘요 }}</h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs



만약 v-pre 를 없에면 페이지에 아무것도 안나타나게 된다.

다시 실행을하면 컴파일에 실패했다는 오류가 뜬다. 




[ 오류 메시지 ]









8) v-cloak 디렉티브


v-cloak을 설명하기전에 이 동작부터 확인해 본다.





다시 실행될때 아까의 if else-if ... 의 숨겨져있던 엘리먼트들이 짧은 순간에 잠깐 나오게 되는데..


그 이유는, 아직 자바스크립트 코드가 실행되기 전이라 그렇다.


지금까지 코드들을 보면 머스태쉬 태그를 작성하지 않았지만,

작성했더라면 머스태쉬태그도 그대로 나왔을 것이다


만약에 자바스크립트가실행 되기전에, 즉 Vue 인스턴스가 제대로 준비되기 전까지 

HTML코드를 숨기고 싶을 때 v-cloak이라는 디렉티브를 사용한다


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app" v-cloak>
      <h1 v-if="value > 5">value 가 5보다 크군요</h1>
      <h1 v-else-if="value === 5">값이 5네요</h1>
      <h1 v-else>value 가  5보다 작아요</h1>
      <h1 v-pre>{{ 이건 그대로 렌더링해줘요 }}</h1>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


이렇게만 한다고해서, 제대로 적용되지는 않는다. 


추가적으로 할 작업이 있는데, 

v-cloak은 CSS 부분에서 해당attribute가 있는 경우 display: none 스타일을 적용해야 숨겨진다.



CSS

1
2
3
[v-cloak]{
  display: none;
}
cs




[결과]

















9) v-once 디렉티브


이 디렉티브를 사용하면, 

컴포넌트를 초기에 딱 한번만 렌더링한다

즉, 자바스크립트에서 사용하는 데이터를 사용하긴 하는데,

변동이 없고 한결같은 정적인 부분을 보여줄 때 사용한다.


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app" v-cloak>
      <h1 v-once v-if="value > 5">value 가 5보다 크군요</h1>
      <h1 v-else-if="value === 5">값이 5네요</h1>
      <h1 v-else>value 가  5보다 작아요</h1>.
      <h2 v-once>초기 값: {{ value }}</h2>
      <h2>현재 값: {{ value }}</h2>
      <h1 v-pre>{{ 이건 그대로 렌더링해줘요 }}</h1>   
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs



14번 줄의 v-once 디렉티브를 사용하여

초기에 한번 렌더링을 하도록 설정하고,

15번줄에는 그냥 value를 그대로 보여주게 했다.



[결과]









자 여기서부터는 위의 디렉티브보다 사용개념이 조금 어려울 수 있기 때문에 따로 분류를 했다.








10) v-bind 디렉티브



HTML엘리먼트의 속성을 설정할 땐 어떻게 하나.


{{ 머스태쉬 태그 }} 를 사용해서 name값을 설정하도록 해본다.

이렇게 HTML 태그안의 내용을 Vue인스턴스안의 데이터값으로 설정 할 수 있다.

하지만, HTML태그의 속성 값을 데이터값을 사용해야 한다면 어떻게 해야 할까?



예를들어서 이미지 태그 

1
<img src="링크"/>
cs
의 링크부분에서 데이터 값을 사용하고 싶다면


ex) 잘못된 예 

1
<img src={{ image }}/> 라던지 <img src"{{ imase }}"/>
cs

이렇게 하면 작동되지않고, 에러가 발생한다 (전자의 경우 작동만 안하고 오류는 발생하지 않음)


Error

[Vue warn]: src=”{{image}}”: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id=”{{ val }}”>, use <div :id=”val”>.

이 부분을 해결해주는게 v-bind 이다.






- 사용법

1
<img v-bind:src="image"/>
cs

와 같은 형식으로 하면 된다.

v-bind: 뒤에 속성의 이름을 넣어주면 된다.


JS

1
2
3
4
5
6
7
8
9
// 새로운 뷰를 정의합니다
var app = new Vue({
  el: '#app'// 어떤 엘리먼트에 적용을 할 지 정합니다
  // data 는 해당 뷰에서 사용할 정보를 지닙니다
  data: {
    name'Vue',
    feelsgood: 'https://imgh.us/feelsgood_1.jpg'
  }   
});
cs



HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello, {{ name }}</h1>
    <img v-bind:src="feelsgood"/>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs



[결과]




- 더 단순하게 사용하는 방법


편의를 위해서 v-bind를 생략 할 수있다.

그냥 :속성 만 넣어주면 된다.


ex) v-bind:src


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello, {{ name }}</h1>
    <img :src="feelsgood"/>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs





- 응용하기


사실 머스태쉬태그나, 디렉티브를 사용 할 때, 

그 내부의 값을 꼭 데이터명으로 해야 하는건 아니다

그안에 자바스크립트 표현식을 사용 할 수도 있다.


이런식으로도 할 수있다.








Vue인스턴스의 데이터 안에 smile값에 따라 다른 이미지를 보여주게 해본다.


JS

1
2
3
4
5
6
7
8
9
10
11
// 새로운 뷰를 정의합니다
var app = new Vue({
  el: '#app'// 어떤 엘리먼트에 적용을 할 지 정합니다
  // data 는 해당 뷰에서 사용할 정보를 지닙니다
  data: {
    name'Vue',
    smile: true,
    feelsgood: 'https://imgh.us/feelsgood_1.jpg',
    feelsbad: 'http://imgh.us/feelsbad.jpg'
  }   
});
cs



HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello, {{ name }}</h1>
    <h2>{{ Date() }}</h2>
    <img :src="smile ? feelsgood : feelsbad"/>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs

삼항 연산자를 통해서도 바꿀 수 있다. 



app.smile 값을 변경하면 이렇게 이미지도 true / false에 따라 변화 한다 

[결과]










11) v-for 디렉티브


HTML에서 for-loop을 구현하기 위하여 사용된다.

즉, 비슷한 내용을 반복적으로 보여줄 때 사용되는 것이다.

실제 프로젝트에서도 자주 사용되는 개념이다.


예를들어서, 

- 게시판의 게시물 목록을 렌더링 할 때, 이 디렉티브가 사용된다.

- 덧글의 목록을 렌더링 할때도 사용된다.


이런식으로 무언가의 목록을 구현 할 때 주로 사용되는 디렉티브이다.



- 사용


JS

1
2
3
4
5
6
7
8
9
10
var app = new Vue({
  el: '#app'
  data: {
    todos: [
      { text: 'Vue.js 튜토리얼 작성하기' },
      { text: 'Webpack2 알아보기' },
      { text: '사이드 프로젝트 진행하기' }
    ]
  }   
});
cs



v-for 디렉티브 사용


이 디렉티브를 반복할 태그에서 사용하면 되는데 ( 지금은 li태그가 되겠다 )

이 디렉티브는 item in items 의 형식으로 작성한다.


여기서 items 는 Vue엘리먼트의 데이터 안에 들어있는 배열 이름

(이번 경우엔 todos가 된다.)으로 설정하고,


item은 렌더링 하게 될 때,

각 원소를 가르키는 별침(alias)이다.

(이번 경우엔 todo가 되고 이건 별칭이라 사실 마음대로 작성해도 된다.)



HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h2>오늘 할 일</h2>
    <ul>
      <li v-for="todo in todos">{{ todo.text }}</li>
    </ul>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


이렇게 todos의 데이터를 for문을 돌릴 수 있다.





index 값 받아오기


[ (todo, index) in todos ]




이렇게 index를 가져 올 수 있다.











12) v-model 디렉티브




데이터 → 뷰의 형태로 바인딩이 되어있어서,

데이터의 값이 변하면 바로 바로 업데이트가 된다.


그러면 양 방향 바인딩은 무엇인가?


뷰 ⇄ 데이터 형태로 바인딩하여 데이터가 양방향으로 흐르게 해주는 것이다.

즉, 데이터에 있는 값이 뷰에 나타나고,

이 뷰의 값이 바뀌면 데이터의 값도 바뀌는 것이다.







- 사용 


HTML에서 input태그를 작성하고, 

그 태그의 v-model 디렉티브를 데이터 레퍼런스 이름으로 설정한다.

우리의 경우엔 name이 되겠다.


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello, {{ name }}</h1>
    <input type="text" v-model="name"/>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


v-model을 설정함으로서, 

이 input엘리먼트의 값이 업데이트되면 name값이 자동으로 바뀌게 한 것






- 응용 하기


체크박스 인풋을 만들고,

v-model값을 smile로 설정하면


HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="app">
    <h1>Hello, {{ name }}</h1>
    <h3><input type="checkbox" v-model="smile"/>웃어요 개구리</h3>
    <img :src="smile ? feelsgood : feelsbad"/>
  </div>
  
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</body>
</html>
cs


이렇게 설정해주고 나면, 

체크박스의 값이 업데이트 될 때마다 자동으로 

뷰 인스턴스의 데이터 모델이 업데이트됩니다.






13) v-on 디렉티브







출처 : https://velopert.com/3044

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

Vue - 라이프 사이클  (0) 2019.06.27
Vue - $nextTick  (1) 2019.04.16
Vue - 인스턴스  (0) 2019.03.15
Vue - Mustache(콧수염) 템플릿  (0) 2019.03.13
Vue - Vue란  (0) 2019.03.13
Comments