본문 바로가기
PROGRAM/Script Language

[Vue.js 시작하기] 2. Vue.js 사용을 위한 기본 문법 1

by ojava 2021. 3. 21.
반응형

Vue.js를 시작하기 위해 다양한 사이트를 서치해보니, 문법을 설명해주는 다양한 사이트가 있다.

물론 책을 사서 공부해도 좋겠지만, 가볍게 시작하는 마음으로 보기에 괜찮은 사이트들을 추천해주고 해당 사이트에서 제공하고 있는 기본 문법들에 대해 소개한다.

 

~ 출처 및 참고 사이트 ~

kr.vuejs.org/v2/guide/index.html
www.vuemastery.com/courses/intro-to-vue-js/vue-instance


Vue Instance 만들기 / 데이터 바인딩 (선언적 렌더링)

 

문법 공부를 위한 간단한 페이지 개발용이므로, script를 직접 추가하는 방식으로 시작하자.

study.html 파일을 만들고, vue instance를 선언할 별도의 main.js 파일을 만들어서 import 하는 아래의 예제를 참고하면 아주 간단한 방식으로 instance 생성 및 이를 통해 값을 표현하는 방식을 볼 수 있다.

 

<!-- study.html -->
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
    <div id="app">
    	 <!-- vue instance에 선언된 데이터를 불러오는 부분, Expression -->
        <h1>{{ product }}</h1>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="main.js"></script>
</body>
</html>
// main.js
var app = new Vue({
    el: '#app', // 선언한 vue instance가 적용될 element
    data : {
        product : 'Socks' // vue instance에서 불러들일 데이터
    }
})

 

예제를 수행해보면 알 수 있지만, main.js에 선언한 app의 data 값을 바꾸게 되면 이를 가져다 쓰는 내용도 바뀌게 된다. 이를 반응형이라고 부르고, Reactive라는 성격으로 표현한다.
product에 선언한 Socks가 아니라 Hats로 바꾸거나 Pants로 바꾸는 등, 손쉽게 정보를 바꿀 수 있다.

추가로 작성한 내용을 크롬 console에서 불러오고 수정할 수도 있다.

app.product를 입력하면, 기존에 작성했던 Socks를 불러오는 것을 볼 수 있고 이를 변경해서 선언하니 화면에 변경된 product인 Hoods가 뜬다.

 

Vue.js에서 데이터 바인딩 방식으로 가장 기본적으로 사용하는 건 괄호로 두 번 감싸주는 {{ mustache }} 구문이다.
화면에 값을 표시할 때 주로 사용하며, 다음과 같은 내용들도 지원한다.

  • {{ count + 1 }} : 간단한 계산
  • {{ firstName + ' ' + lastName }} : 텍스트간의 결합
  • {{ clicked ? true : false }} : 삼항연산자 
  • {{ message.split('').reverse().join('') }} : string 변환 관련 함수 사용

위와 같은 방식은 선언적 렌더링이라고 한다.

 

반응형

 


Directive : v-bind

위 내용처럼 선언된 데이터를 태그의 attribute에도 바인딩할 수 있을까?
img 태그를 추가하고, data에 image라는 값을 추가한 뒤에 경로를 가져오도록 해봤다.

 

아 물론 저 경로에 이미지가 없어서 공허한 네모박스가 뜨지만, 일단 저런 형태로 데이터 바인딩을 할 수 없다고 에러메시지가 아주 친절하게 나온다.

더보기

[Vue warn]: Error compiling template:

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">.

2  |          <div class="product">
3  |              <div class="product-image">
4  |                  <img src="{{ image }}">
   |                       ^^^^^^^^^^^^^^^^^
5  |              </div>
6  |  

(found in <Root>)

{{ }} 형태가 아니라, 태그에 사용할 수 있는 바인딩 속성이 존재한다.
Vue.js에서는 이를 디렉티브 (Directive) 라고 부르며 v-를 접두사로 한 몇 가지 종류가 존재한다.

이 중 html 태그의 attribute에 값을 선언할 때 사용하는 v-bind가 있다. 
만약 img 태그의 src 경로로 값을 지정하고 싶다면 아래와 같이 선언하면 된다.

<!-- vue.js의 directive 사용하여 attribute에 값 바인딩 -->
<img v-bind:src="image">

<!-- v-bind는 shorthand를 제공한다. 단순화하여 :속성명으로 사용해도 무관하다 -->
<img :src="image">

 

v-bind의 사용 방식은 아래와 같이 v-bind:속성명 과 같이 사용할 수 있으며, v-bind:속성명을 줄여서 :속성명 으로 사용도 가능하다.

  • v-bind:alt="description"
  • v-bind:href="url"
  • v-bind:title="toolTip"
  • v-bind:class="className"
  • v-bind:style="styleString"
  • v-bind:disables="disabledType"

 

a 태그의 href 속성에 app.url에 선언한 값이 제대로 바인딩 되어서 원하는 링크로 연결되고 있다.


Directive : v-if, v-for, v-on

디렉티브는 앞에서도 소개했지만, v- 접두사를 붙인 속성값으로 HTML 태그에 적용할 수 있는 항목이다.
API 문서에서 정의된 바로는 현재 총 14개의 디렉티브가 확인된다.
이 중 자주 사용될 것으로 생각되는 디렉티브에 대해서만 별도로 소개한다.

참고 vue.js API 내 디렉티브 문서 : kr.vuejs.org/v2/api/#%EB%94%94%EB%A0%89%ED%8B%B0%EB%B8%8C

 

1) v-if 를 통한 조건문

태그를 특정 조건에 맞추어 표시해야 하는 경우 사용할 수 있다.
기본적인 if/else문과 유사하게 v-if와 더불어 v-else, v-else-if를 이용하여 조건에 따른 분기를 할 수 있다.

<!-- v-if와 v-else 사용 예시 -->
<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>

<!-- v-if와 v-else, v-else-if 사용 예시 -->
<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>

 

2)  v-for 를 통한 반복문

이 역시도 기본적인 반복문인 for문과 유사하게 사용할 수 있으며, instance에 선언된 데이터를 기반으로 반복적으로 데이터를 불러오도록 할 수 있다.

해당 데이터 항목으로 바인딩할 수 있는 형태는 Array, Object, number, string, Iterable 등이 존재한다.

<!-- 원본 데이터를 기반으로 엘리먼트 또는 템플릿 블록을 여러번 렌더링합니다. -->
<!-- 여러개의 데이터를 포함하는 형태의 items 라는 데이터가 존재하고 이를 사용함 -->
<div v-for="item in items">
  {{ item.text }}
</div>

<!-- 또는, 인덱스(아니면 객체의 경우 키)의 별칭을 지정할 수 있습니다. -->
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, name, index) in object"></div>

<!-- 강제로 엘리먼트의 순서를 바꾸려면 특수 속성 key를 설정해야 합니다. -->
<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'ojava의 Vue.js 시작하기' },
      { text: '개발환경은 세팅하셨나요?' },
      { text: '오늘은 기본 문법을 알아봅시다' }
    ]
  }
})

 

3) v-on 을 통한 이벤트 리스너 연결

jQuery에서는 특정 ID를 기반으로 이벤트 리스너를 연결할 때 $("#btn_like").on("click", function~~ 와 같은 형태로 이벤트 리스너를 연결해왔을텐데, vue.js에서도 이러한 형태의 이벤트 핸들러를 제공한다.
Directive 중에서 v-on이 이러한 역할을 수행한다.

v-on의 내용는 미리 정의된 Function, 인라인 메소드나 실제 수행되는 내용을 간략히 기술한 Inline Statement 또는 별도로 수행될 수 있는 Object 가 올 수 있다. 전달인자로는 별도의 매개변수 혹은 event 값 등이 전달 될 수 있다.

<div id="app">
    <!-- 수행해야 할 내용을 직접 작성해도 된다. -->
    <button v-on:click="likeCount += 1">좋아요</button>

    <!-- vue instance에 별도로 선언한 methods를 연결할 수 있다. -->
    <button v-on:click="addLike"></button>

    <!-- 인라인 메소드 핸들러 -->
    <button v-on:click="sendMessage('awesome!')"></button>

    <!-- 추가로 $event 인자를 전달해주면, 함수에서 DOM 이벤트 객체 사용 가능 -->
    <button v-on:click="eventCall('awesome!', $event)"></button>
</div>
new Vue({ 
	el: '#app',
    data: { likeCount : 0 },
    methods : {
    	addLike : function(event) {
        	alert("좋아요!");
            likeCount += 1;
            
            // function에 정의한 event는 DOM 이벤트
            if (event) {
            	alert(event.target.tagName);
            }
        },
        sendMessage : function(message) {
        	alert(message);
        },
        eventCall : function(message, event) {
        	// method 호출 시, $event를 전달받으면 DOM 이벤트 객체를 사용할 수 있다.
            if (event) {
            	event.preventDefault();
            }
            alert("이벤트를 호출했어요.");
        
        }
    }
});

 

앞에서 다뤘던 v-bind는 :속성명 형태로 단축하여 사용할 수 있었다면, v-on은 @으로 단축하여 사용할 수 있다.
추가로 이벤트 리스너와 함께 사용할 수 있는 수식어가 아래와 같이 정의되어 있는데, 해당 내용은 예제를 보면 조금 더 이해가 쉽다.

  • 이벤트 수식어:
    • .stop - event.stopPropagation() 을 호출합니다.
    • .prevent - event.preventDefault() 을 호출합니다.
    • .capture - 캡처 모드에서 이벤트 리스너를 추가합니다.
    • .self - 이벤트가 이 엘리먼트에서 전달된 경우에만 처리 됩니다
    • .{keyCode | keyAlias} - 특정 키에 대해서만 처리 됩니다.
    • .native - 컴포넌트의 루트 엘리먼트에서 네이티브 이벤트를 수신합니다.
    • .once - 단 한번만 처리됩니다.
    • .left - (2.2.0) 왼쪽 버튼 마우스 이벤트 트리거 처리기.
    • .right - (2.2.0) 오른쪽 버튼 마우스 이벤트 트리거 처리기.
    • .middle - (2.2.0) 가운데 버튼 마우스 이벤트 트리거 처리기.
    • .passive - (2.3.0+) DOM 이벤트를 { passive: true }와 연결합니다.
<!-- v-on은 @를 이용해서 단축해서 사용할 수 있다. -->
<button @click="doThis"></button>

<!-- 전파 금지 / onclick 이벤트에 stopPropagation() 수행함과 같다. -->
<button @click.stop="doThis"></button>

<!-- 기본 동작 방지 / onclick 이벤트에 preventDefault() 수행함과 같다. -->
<button @click.prevent="doThis"></button>

<!-- 표현식이 없는 기본 동작 방지 / form submit 시, -->
<form @submit.prevent></form>

<!-- 수식어 chaining / stop > prevent 순차적으로 수행 -->
<button @click.stop.prevent="doThis"></button>

<!-- 키 코드 (keyCode) 를 이용한 키 입력 수식어 -->
<input @keyup.13="onEnter">

<!-- 키 별칭 (keyAlias) 을 이용한 키 입력 수식어 / keycode 13에 대해 수행함과 같다. -->
<input @keyup.enter="onEnter">

<!-- 버튼에 대해 선언된 click 이벤트는 once로 인해 한 번만 수행된다. -->
<button v-on:click.once="doThis"></button>

관련하여 keycode = 13이 enter임은 다들 익숙해서 알고 있겠지만, 추가로 사용이 가능한 keyAlias에 대해 알아보자.

  • .tab (keycode = 9)
  • .delete (삭제를 수행하는 키 모두 인식함. BACKSPACE keycode = 8, DEL keycode = 46)
  • .esc (keycode = 27)
  • .space (keycode = 32)
  • .up (keycode = 38)
  • .down (keycode = 40)
  • .left (keycode = 37)
  • .right (keycode = 39)

 

추가로 v-on 디렉티브와 관련하여 버전별로 추가된 기능에 대해서 별도 기술하고 있다.

  • 사용방법:2.4.0부터 v-on도 인수없이 이벤트/리스너 쌍의 객체에 바인딩을 지원합니다. 객체 구문을 사용할 때는 수식어를 지원하지 않습니다.네이티브 DOM 이벤트를 수신하면 메소드는 네이티브 이벤트를 유일한 전달인자로 받습니다. 인라인 구문을 사용하는 경우 명령문은 특별한 $event 속성에 접근할 수 있습니다: v-on: click = "handle('ok', $event)"
  • Starting in 2.4.0+, v-on also supports binding to an object of event/listener pairs without an argument. Note when using the object syntax, it does not support any modifiers.
  • 일반 엘리먼트에 사용되면 기본 DOM 이벤트만 받습니다. 사용자 정의 컴포넌트에서 사용될 때 해당 하위 컴포넌트에서 생성된 사용자 정의 이벤트를 받습니다.
  • 엘리먼트에 이벤트 리스너를 연결합니다. 이벤트 유형은 전달인자로 표시됩니다. 표현식은 메소드 이름 또는 인라인 구문일 수 있으며, 수식어가 있으면 생략할 수 있습니다.
<!-- 객체 구문 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

<!-- dynamic event (2.6.0+ 부터 지원) -->
<button v-on:[event]="doThis"></button>

<!-- dynamic event의 약어 (2.6.0+ 부터 지원) -->
<button @[event]="doThis"></button>

 

 

제일 기초적이고 기본적인 문법을 다뤘지만, 실질적인 양방향 통신을 위한 방법을 다루지 않았다.

위에 작성한 디렉티브를 제외하고 주요하게 다뤄야 하는 항목이 하나 더 있는데 바로 입력값에 대해 양방향 통신을 할 수 있게 하는 v-model이다. 이를 이용해서 폼을 이용한 데이터 통신을 어떻게 수행하는지 다뤄보고, 또한 반복적으로 사용해야 하는 항목을 모듈화해주는 컴포넌트 구성방법에 대해서도 다뤄보자.

반응형