Vue에서의 템플릿은 Vue로 화면을 조작하는 방법을 말한다. 템플릿 문법은 크게 데이터 바인딩과 디렉티브로 나뉜다. 하나씩 알아보도록 하자.

🔗 Data Binding

데이터 바인딩(Data Binding)은 Vue 인스턴스에서 정의한 속성들을 화면에 표시하는 방법이다. 보통 머시태시({{}}) 문법을 사용한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">{{ message }}</div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      let vm = Vue.createApp({
        name: "App",
        data() {
          return {
            message: "Hello Vue3!",
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

예제 코드를 보면 <div> 안에 머스태시 괄호를 이용해서 Vue 인스턴스의 message 속성을 연결한 것을 볼 수 있다.

 

🛎️ Vue 인스턴스?

인스턴스는 Vue로 개발할 때 필수로 생성해야 하는 코드를 말한다. 위의 예제 코드에서 Vue.createApp()을 이용해서 인스턴스를 생성할 수 있다. 인스턴스 안에는 미리 정의되어 있는 속성과 메서드(API)들이 있기 때문에 해당 기능들을 이용해서 빠르게 화면을 개발할 수 있다. 인스턴스에서 사용할 수 있는 주요 속성들에 대해 간단히 말하자면…

Vue.createApp({
	template: ,  // 화면에 렌더링되는 녀석들
	data: ,  // 반응형 데이터 속성
	methods: ,  // 이벤트 로직을 제어하는 메서드
	created: ,  // 뷰의 라이프사이클에서의 부가 작업
	watch: ,  // data에서 정의한 속성에 변화가 일어났을 때 추가 동작을 수행할 수 있게 정의하는 속성
});

참고로 Vue2에서는 el이라는 속성이 있었지만, Vue3로 넘어오면서 해당 속성을 사용하지 않고 mount() API만 사용한다.

 

🪝 Directives

디렉티브(Directives)는 Vue로 화면의 요소를 더 쉽게 조작할 수 있게 하는 문법이다. v- 접두사가 붙은 특수 속성으로 직역하면 말 그대로 “지시” 를 뜻한다. 쉽게 말해, 디렉티브는 컴포넌트나 DOM 요소에게 “~ 하게 작동할 것” 을 지시해주는 지시문인 셈이다. 디렉티브는 아래와 같이 구성되어 있다.

어떤 디렉티브들이 있는지 직접 보면서 알아보도록 하자.

 

💬 v-text & v-html 디렉티브

둘 다 텍스트를 출력하는 디렉티브지만, 둘의 차이는 문자열을 “그대로 텍스트로 넣느냐”, HTML로 해석해서 넣느냐” 다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <span v-text="message"></span>
      <span v-html="message"></span>
      <span>{{ message }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      let vm = Vue.createApp({
        name: "App",
        data() {
          return {
            message: "<b>Hello Vue3!</b>",
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

보다시피 v-text는 텍스트를 그대로 뱉어내고, v-html은 HTML 요소는 HTML로 해석해서 뱉어낸다. 보통 v-text 디렉티브를 사용할 것을 권장한다. 왜냐하면 사용자가 입력한 값을 그대로 v-html에 넣으면 악성 스크립트가 섞일 수도 있기 때문이다. 이걸 보통 XSS(Cross-Site Scripting) 문제라고도 한다.

 

⛓️ v-bind

이 디렉티브는 Vue 데이터와 HTML 속성을 연결해주는 디렉티브다. 바인딩은 말 그대로 “연결한다” 는 의미인데, Vue에서의 바인딩은 보통 data에 있는 값화면(HTML 요소)을 연결하는 것을 말한다.

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <div id="app">
            <input type="text" v-bind:value="message" />
            <br />
            <img v-bind:src="imagePath" />
        </div>
        <script src="https://unpkg.com/vue"></script>
        <script>
            let viewModel = Vue.createApp({
                name: 'App',
                data() {
                    return {
                        message: 'v-bind 디렉티브',
                        imagePath:
                            'https://img.freepik.com/free-photo/shot-tiger-laying-ground-while-watching-his-territory_181624-44049.jpg',
                    };
                },
            }).mount('#app');
        </script>
    </body>
</html>

일반적으로 HTML은 정적인 문서지만, 동적인 UI를 만들고 싶어서 Vue를 사용하는 것이다. 그래서 속성값도 고정된 값이 아니라 데이터의 값에 따라 달라지길 원하기 때문에 v-bind가 필요한 것이다. 여기서 짚고 넘어가야 할 점은 v-bind 디렉티브는 단방향으로만 데이터를 바인딩한다는 점이다. 즉, Vue 인스턴스의 데이터나 속성이 바뀌면 UI를 갱신한다는 것이다.

렌더링된 화면을 보면 알 수 있듯이 화면에 바인딩된 요소에서 값을 변경하더라도 데이터가 바뀌지 않는 것을 볼 수 있다. 콘솔에서 viewModel.message="단방향임..." 으로 속성에 직접 값을 할당해서 데이터를 변경해야 UI도 변경된다.

 

↔️ v-model

앞서 살펴봤던 디렉티브들과는 다르게 v-model은 폼 입력 요소의 값과 Vue 데이터를 양방향으로 연결하는 디렉티브다. 쉽게 말해 데이터가 바뀌면 입력창 화면도 바뀌고, 사용자가 입력창 값을 바꾸면 데이터도 같이 바뀐다는 것이다.

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model="name" />
            <br />
            입력한 값: <span>{{name}}</span>
        </div>
        <script src="https://unpkg.com/vue"></script>
        <script>
            let viewModel = Vue.createApp({
                name: 'App',
                data() {
                    return {
                        name: '',
                    };
                },
            }).mount('#app');
        </script>
    </body>
</html>

그리고 checkboxselect 요소에서의 v-model은 다중 선택인지 단일 선택을 하는지에 따라 양방향 데이터 바인딩으로 값을 받아내기 위한 데이터의 형식이 달라진다. 다중 선택은 배열을 사용해야 하고, 단일 선택은 문자열로 값을 받아내야 한다. 그리고 checkbox, radio와 같이 input 요소를 사용하는 경우는 각각의 input 요소마다 v-model 디렉티브를 적용해야 하지만, select와 같이 값을 선택하는 요소를 감싸는 부모 요소가 있다면 부모 요소인 selectv-model 디렉티브를 한 번만 적용해야 한다는 점도 알아두도록 하자.

 

↪️ v-if & v-for

v-if 디렉티브는 느낌 그대로 화면 렌더링에서의 if문이라고 생각하면 된다. 조건이 참이면 화면에 렌더링되고, 거짓이면 아예 렌더링되지 않는다. 그냥 조건이 거짓이면 DOM에 아예 만들지 않는다는 점만 기억해두도록 하자.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      잔고: <input type="text" v-model="deposit" />
      <br />
      회원 등급:
      <span v-if="deposit > 1000000">Gold</span>
      <span v-else-if="deposit >= 500000">Silver</span>
      <span v-else-if="deposit >= 200000">Bronze</span>
      <span v-else="deposit">Basic</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      let viewModel = Vue.createApp({
        name: "App",
        data() {
          return {
            deposit: 0,
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

 

v-for 디렉티브도 느낌 그대로다. 배열이나 객체 데이터를 반복해서 화면에 출력하는 디렉티브다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <ul>
        <li v-for="item in items">{{item}}</li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      let vm = Vue.createApp({
        name: "App",
        data() {
          return {
            items: ["맥북 프로", "아이패드 프로", "에어팟 프로"],
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

v-for="(item, index) in items"처럼 인덱스 정보도 추가로 뿌려줄 수 있고 객체도 각 속성들을 뽑아서 뿌려줄 수도 있다. 그리고 나중에 요소가 많아지는 상황에서 반복 렌더링할 때는 보통 :key를 같이 사용한다. 아래 예제 코드를 살펴보고 넘어가도록 하자.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <ul>
        <li v-for="item in items" :key="item.id">{{ item.text }}</li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      let vm = Vue.createApp({
        name: "App",
        data() {
          return {
            items: [
              {
                id: 1,
                text: "맥북 프로",
              },
              {
                id: 2,
                text: "아이패드 프로",
              },
              {
                id: 3,
                text: "에어팟 프로",
              },
            ],
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>
profile
판교 함 가보자

0개의 댓글