Vue.js 기본 사용법

taese0_0ng·2021년 4월 4일
2

Vue

목록 보기
1/2
post-thumbnail

Vue.js 도입


<!DOCTYPE html>
<head>
    <title>Vue.js 시작하기</title>
    <script src="https://unpkg.com/vue@2.5.17"></script>
</head>

<body>
    <div id="app">
        <p>
            {{message}}
        </p>
    </div>
</body>

<script>
    console.log(typeof Vue !== 'undefined');
    new Vue({
        el: '#app',
        data: {
            message: '안녕하세요!'
        }
    })
</script>

'https://unpkg.com/vue'에서 CDN을 통해 항상 버전이 배포된다. 2.5.17버전을 특정해 사용했다.
해당 URL을 통해 로딩이 끝나면 Vue라는 전역 변수가 정의 된다.

Vue 객체


Vue라는 객체는 여러가지 역할을 갖는다. 일반적인 함수 호출과는 다릴, 생성자로 사용하려면 new 연산자를 사용하면 된다. 이렇게 생성된 객체를 "Vue 인스턴스"라고한다.

데이터 바인딩


  • 템플릿에서 Mustache 문법(" {{ data }} ")을 이용한 데이터 전개를 한다.
  • 데이터를 수정하면 자동으로 뷰도 수정된다.
<p>{{ message }}</p> //message에는 Vue객체의 data값이 들어간다.

속성값 전개하기

텍스트 외에 DOM 요소의 속성에도 값을 전개할 수 있다. 속성에 값을 전개하려면 Mustache문법 대신 Vue.js가 제공하는 디렉티브인 v-bind를 사용한다.

<script src="https://unpkg.com/vue@w.5.17"></script>
<button id="b-button" v-bind:title="loggedInButton">구매</button>
<script>
var vm = new Vue({
	el:'#b-button',
	data:{
		loggedInButton:'로그인 후에 구매 가능합니다.'
	}
})
</script>

참 혹은 거짓을 값으로 갖는 데이터를 사용할 수도 있다.

<script src="https://unpkg.com/vue@w.5.17"></script>
<button id="b-button" v-bind:disabled="!canBuy">구매</button>
<script>
var vm = new Vue({
	el:'#b-button',
	data:{
		canBuy: false
	}
})
</script>

v-bind값이 참이면 DOM요소에 disable 속성이 추가된다. '반대로 거짓이면 disabled속성이 삭제된다. 참/거짓의 이진값이 그대로 넘어가는 것이 아니라 처리된 결과가 반영된다.
disabled=false와 같이 되는게 아니다.

Javascript 표현식 전개하기

Mustache 문법에는 데이터 바인딩뿐만 아니라 자바스크립트 표현식도 전개가 가능하다.
{{ }} 안에서뿐만 아니라 속성값도 마찬가지다.
자바스크립트 표현식은 각 바인딩의 하나의 단일 표현식만 사용할 수 있다는 사실을 주의하라.

<p>{{ items[0].price * items[0].quantity }}</p>

필터


필터는 일반적인 텍스트 포매팅 기능을 제공하며, 생성자 옵션 중 한 가지다.
Date 객체를 YYYY/mm/dd와 같은 포맷으로 변환하거나 숫자 0.5를 퍼센트단위('50%')로 변환하는 경우 등에 사용한다.
정의 해 둔 필터는 템플릿에서 {{ }} 문법과 |(파이프) 연산자를 조합해 사용한다.

filters:{
	필터명: function(value){
		//return ...
	}
}
{{| 필터명 }}

예제

<p>필터 예제 {{1000 | numberWithDelimiter }}</p>
var vm = new Vue({
	el : ...,
	data: {...},
	filters:{
		numberWithDelimiter: function(value) {
			if(value){ return '0' }
			return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')
		}	
	}
})

필터는 인자로 받은 값을 문자열로 변환한 다음, 이문자열에 3자리마다 콤마를 추가하는 간단한 함수다.
화면에는 콤마가 찍힌 1,000이 출력될 것이다.

{{ value | filterA | filterB }}

필터를 여러 개 연결해서 사용할 수 있다. 어떤 필터로 처리한 값이 다시 다음 필터의 입력으로 들어가는 형태이다.

계산 프로퍼티(computed)


계산 프로퍼티(computed)는 어떤 데이터에서 파생된 데이터를 프로퍼티로 공개하는 기능으로, Vue 생성자의 옵션 객체의 한 가지다.

데이터를 모종의 방법으로 처리한 값을 프로퍼티로 삼고 싶을 때 이 계산 프로퍼티를 사용하는데, 대개는 복잡한 식을 템플릿에 나타내는 용도로 사용된다.

new Vue({
	//...
	computed: { //함수 형태로 구현함, 참조할 때는 프로퍼티처럼 동작.
		계산 프로퍼티 이름 : function () {
			//return ...
		}
	}
})
<div id="app">
	<p> 
	합계 : {{ items.reduce(function (sun,item) { return sum + (item.price * item.quantity), 0);}}
	</p>
</div>

Mustache 문법으로 작성한 예도 일단 원하는 대로 동작은 한다. 그러나 해당 코드 줄이 너무 길고 계산하는 값이 무엇인지 한눈에 이해하기 어렵다.

...
<p> 합계(세금포함) : {{ totalPriceWithTax }}</p>
...

<script>
new Vue({
	// ...마운트 및 데이터 정의
	computed: {
		totalPrice: function () {
			//this를 통해 인스턴스 안의 데이터에 접근
			return this.items.reduce(function (sum, item) { 
				return sum + (item.price * iteam.quantity)
			}, 0)
		},
		totalPriceWithTax: function () {
			//계산 프로퍼티에 의존하는 계산 프로퍼티도 정의 가능함
			return Math.floor(this.totalPrice * 1.10)
		}
	}
})
</script>

정의된 프로퍼티는 데이터와 마찬가지로 템플리셍서 전개할 수 있다. 호출을 의미하는()를 사용할 필요는 없다. 함수 형태로 정의 했지만, 참조할 때는 메서드가 아니라 프로퍼티로 취급된다.

조건에 따른 렌더링(v-if, v-show)


템플릿에서 어떤 요소를 조건에 따라 표시하거나 표시하지 않도록 하려면 v-show디렉티브 혹은 v-if디렉트비를 사용한다.

<p v-if="인자">
	// 참이면 화면에 표시, 거짓이면 표시하지 않음
</p>
<p v-show="인자">
	// 참이면 화면에 표시, 거짓이면 표시하지 않음
</p>

v-if와 v-show 용도 차이

v-if와 v-show는 모두 속성값 표현식의 평가 값에 따라 요소를 표시하거나 표시하지 않는 방식으로 동작하는 디렉티브다.

v-if는 평가 값에 따라 DOM 요소를 추가하거나 제거하는 식으로 동작.
v-show는 스타일에 display 프로퍼티 값을 변경하는 방식으로 동작.

일반적으로 스타일을 수정하는 쪽보다 DOM을 수정하는 쪽이 렌더링 비용이 더 크기때문에 평가 값이 빈번하게 바뀌는 경우에는 v-show를 사용해야 한다.
반면 평가 값이 자주 변하지 않는 경우에는 v-if를 사용하여 렌더링 비용을 절약하는 것이 적합하다.

클래스와 스타일 연결하기


v-bind 디렉티브를 사용하여 클래스나 스타일을 평가 값에 따라 변경시킬 수 있다.

클래스 바인딩(v-bind:class)

v-bind:class는 객체를 속성값으로 받으면 값이 참인 프로퍼티의 이름을 class 속성의 값으로 반영한다. 다음과 같은 경우, class속성의 값은 shark가 된다.

<p v-bind:class="{shark: true, mecha: false}"></p>

복잡한 식이 들어가는 경우에는 computed를 사용할 수도 있다.

...
<p v-bind:class="errorMessageClass"></p>
...

<script>
...
computed: {
	errorMessageClass: function(){
		return {
			error: !this.canBuy
		}
	}
}
...
</script>

스타일 바인딩(v-bind:style)

v-bind:style에서는 속성값 객체의 프로퍼티가 스타일 프로퍼티에 대응하며, 인라인 스타일 형태로 반영된다.

<p style="color: red;">a</p> <!-- 일반적인 style -->
<p v-bind:style="{color: 'red'}">a</p>

클래스 바인딩과 같이 표현식을 사용해도 되며, 복잡한 경우 computed를 사용해도 된다.

<p v-bind:style="{border: (canBuy ? '' : '1px solid red'), color: (canBuy ? '' : 'red')}">
1000원 이상부터 구매 가능
</p>
<p v-bind:style="errorMessageStyle">
1000원 이상부터 구매 가능
</p>

<script>
...
computed: {
	errorMessageStyle: function(){
		return {
			border: this.canBuy ? '' : '1px solid red',
			color: this.canBuy ? '' : 'red'
		}
	}
}
...
</script>

v-bind의 생략 표기법

v-bind 디렉티브는 가장 많이 쓰이는 디렉티브 중 하나다. 이 때문에 간결한 표기를 위한 생략 표기법을 지원한다.

v-bind:disabled -> :disabled

<p :class="{error: !canBuy}">
	1000원 이상부터 구매 가능
</p>

리스트 렌더링하기(v-for)


v-for 디렉티브를 사용해서 배열이나 객체의 데이터를 리스트로 렌더링(반복 렌더링)할 수 있다.

주의 해야할 점으로 Vue.js의 성능을 위한 것으로 반드시 부여되는 v-bind:key가 포함되어야 한다.는 것이다. 요소 생성 시 각각의 요소에 유일 키값이 부여된다.

<!-- data: { arr: ['가','나','다']} 를 정의했다고 가정 -->
<ul>
	<li v-for="item in arr" v-bind:key="item">
		{{ item }}
	</li>
</ul>

<!-- 렌더링 결과 -->
<ul>
	<li></li>
	<li></li>
	<li></li>
</ul>

현재 요소의 인덱스 값이 필요하면 다음과 같이 작성하면 된다.

<ul>
	<li v-for="(item, index) in arr" v-bind:key="item">
		{{ index }} {{ item }}
	</li>
</ul>

<!-- 렌더링 결과 -->
<ul>
	<li>0</li>
	<li>1</li>
	<li>2</li>
</ul>

이벤트 핸들링(v-on)


v-on 디렉티브는 이벤트가 일어난 시점에 속성값으로 지정된 표현식을 실행한다. DOM API의 addEventListener와 같은 것이라고 생각하면 된다.

v-on:이벤트이름="값을 평가할 표현식"
<button v-on:click="clickBtn">클릭</button>

<script>
...
methods:{ //뒤에서 다룰 내용
	clickBtn: function(){
		console.log("click!")
	}
}
...
</script>

v-on의 생략 표기법

v-on 디렉티브 역시 자주 사용되는 디렉티브이기 때문에 생략 표기법을 갖추고 있다.

v-on:click -> @click

<button @click="clickBtn">클릭</button>
<!-- 여기서는 @click이 인식안되는 것을 알 수 있다. button색이... -->

생략 표기법은 간혹 서버 사이드 템플릿 엔진에서 문법 오류로 처리되는 경우가 있다.
간혹 @click이 해당 템플릿 문법에 어긋나기 떄문에 오류로 간주한다.
이런 경우에는 생략 표기법을 사용하지 말고 v-on:~, v-bind:~같이 정식 표기법을 사용해야 한다.

폼 입력 바인딩(v-model)


v-model은 양방향 데이터 바인딩을 제공하는 디렉티브이다.

뷰(DOM)에 변경이 일어나면 해당 값을 Vue 인스턴스 데이터에 업데이트한다. 반대로 Vue 인스턴스 데이터가 수정되면 뷰를 다시 렌더링 한다.

<input type="number" v-model="item.quantity" min="0">

위와 같은 코드로 v-on:input과 같은 효과를 얻을 수 있다.

생애주기 훅


Vue 인스턴스는 생성부터 소멸까지 생애주기를 갖는다.

Vue 인스턴스는 중요도가 높은 순간이 있어서 이때 수행할 처리를 미리 등록해두고 해당 시점에 자동으로 그 처리 내용을 호출하게끔 할 수 있다.

이런 기능을 생애주기 훅(lifecycle hook)이라 한다.

생애주기 훅의 종류와 호출 시점

beforeCreate : 인스턴스가 생성된 다음 데이터가 초기화되는 시점
created : 인스턴스가 생성된 다음 데이터 초기화가 끝난 시점
beforeMount : 인스턴스가 DOM요소에 마운트되는 시점
mounted : 인스턴스가 DOM요소에 마운트가 끝난 시점
beforeUpdate : 데이터가 수정돼 DOM에 반영되는 시점
updated : 데이터가 수정돼 DOM에 반영이 끝난 시점
beforeDestroy : Vue 인스턴스가 폐기되기 전
destroyed : Vue 인스턴스가 폐기된 다음

created 훅

created 훅은 인스턴스가 생성되고 데이터가 초기화된 시점에 실행된다. 이 단계는 아직 DOM 요소가 인스턴스와 연결된 상태가 아니다.

그러므로 아직 인스턴스의 $el 프로퍼티와 DOM API의 getElementById, querySelectorAll을 사용해서 DOM 요소를 반환받을 수 없는 상태라는 데 주의해야 한다.

이 훅은 Vuex를 적용하지 않은 소규모 애플리케이션에서 웹API를 통해 데이터 관련 처리를 시작하거나 setInterval, setTimeout을 반복 실행해야 하는 타이머 처리를 시작하는 시작점으로 사용한다.

mounted 훅

mounted 훅은 인스턴스와 DOM 요소가 연결된 시점에 실행된다.
DOM API를 사용할 수 있는 시점이므로 DOM 조작 및 이벤트 리스너 등록은 이 훅을 사용하면 된다.

beforeDestroy 훅

beforeDestroy 훅은 인스턴스가 폐기되기 직전에 실행된다. mounted 훅에서 DOM 요소에 등록한 이벤트 리스너나 타이머 등을 '뒷정리'하는 용도로 사용한다.
이 뒷정리를 제대로 하지 않으면 메모리 누수의 원인이 되므로 사용자 경험을 해칠 우려가 있다.

메서드


메서드는 이름 그대로 Vue 인스턴스의 메서드를 말한다. Vue 인스턴스의 생성자 옵션 객체에서 methods프로퍼티로 정의한다. methods는 데이터 수정 및 서버에 HTTP 요청을 보낼 때 사용한다.

methods: {
	메서드명: function(){
		//원하는 처리
	}
}

v-on 디렉티브의 속성값에 바인딩하고 뷰에서 이벤트가 발생했을 때 호출되는 형태로 사용하는 것이 가장 흔하다. 템플릿에서도 {{ 메서드명 }}과 같이 사용할 수 도 있다.

<button v-on:click="doBuy($event)">구매</button>

이벤트 객체 외에도 템플릿에 인자를 전달하려면 표현식으로 작성하면 된다.

이벤트 객체

v-on 디렉티브 속성값으로 메서드를 지정했다면 기본적으로 이벤트 객체를 인자로 전달받게 된다.

이 이벤트 객체는 이벤트가 발생한 요소와 좌표 등의 정보를 담고 있으며, 표준 DOM API의 addEventListener에서 첫 번째 인자로 받는 이벤트 객체와 동일한 것이다.

methods: {
	메서드이름: function(event){
		//인자 event는 이벤트 객체
	}
}
profile
FrontEnd Developer #myrealtrip

0개의 댓글