WEB/Vue

[Vue] 고양이도 따라할 수 있는 Vue.js 책 리뷰 및 요약

오늘도출근하는다람쥐 2023. 10. 23. 11:50

고양이도 할수있는 Vue.js 책 리뷰 및 복습 (고양이도 할 수 있는데 나도?!)

💡 기초부터 탄탄히 아주 쉬운것 부터 복잡한 것까지(백엔드 개발자 용 Vue.js)

 

🚘 운전을 잘 못하는 사람이 있다

이 사람은 ‘자동차의 동작원리가 어떻게 되어있는지 몰라서 내가 운전을 못하는거야’라고 생각을 했다

하지만 운전을 잘하기 위해서는 꼭 자동차의 동작원리를 알 필요는 없다고 생각한다

운전을 어떻게 하는지만 알면 된다

그럼 이제 Vue.js라는 자동차를 운전하는 방법을 배워보자

 

🗨️ 머리말

정말 간단하게 Vue.js를 체험해보자

 

🔽 index.html 파일

<!DOCTYPE html>
<html lang="en">
<body>
    <div id="app">
        <h1>{{ message }}</h1>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                message: 'Hello Vue.js!'
            }
        })
    </script>
</body>
</html>

브라우저에 이렇게 작성한 HTML 파일을 읽어 들이기만 해도 Vue.js 애플리케이션이 실행되며, 화면에 다음과 같이 출력이 된다

{{ message }} 부분에 app.message에서 작성한 &lsquo;Hello Vue.js&rsquo;를 표시하고 있다
개발자 도구를 열어서 app.message의 값을 변경하는 순간 자동으로 화면에 표시되었던 내용도 변경되었다

 

이처럼 자바스크립트의 데이터를 변경하기만 하면, 렌더링 내용도 함께 변경되는 것을 데이터 바인딩이라 한다

 

⭐ 왜 Vue.js일까?

낮은 진입장벽 과 적은 학습 비용, 스케일의 우연성, 충실한 공식 문서

💡 백엔드 개발 최대한 초점 맞추고 학습하며, Vue.js는 데이터를 표현(어드민 대시보드) 수준 까지만 학습

 

이해하기 쉬운 템플릿(디렉티브)

<div v-if="show">Hello Vue.js!</div>

v-if 처럼 처음 보는 이상한 속성을 사용하는 것이 처음에는 이상할 수 있지만, 이는 가상 DOM을 만들기 위한 단순한 템플릿 기법이다

이러한 속성은 DOM에 반영되기 전에 Vue.js에 의해 컴파일되며, 이후에는 내부적인 용도로만 사용한다

 

루트 템플릿

<body>
	<div id="app"></div> <!-- 여기에 배치할 예정 -->
</body>

애플리케이션 화면에 출력하려면 일단 어떤 요소에 배치할지를 결정해야 한다

요소의 배치 위치는 body 내부에 있다면 어떤 곳이나 괜찮다

선택자 : #app (배치할 요소와 애플리케이션을 연결하는 것을 마운트(mount)라고 부른다)

 

 

데이터 바인딩

데이터와 렌더링을 동기화하는 구조를 데이터 바인딩이라고 부른다

즉, 데이터에 변경이 있을 때 자동으로 DOM을 업데이트 하는 기능

 

 

'v-'로 시작하는 디렉티브

v-로 시작하는 속성은 디렉티브라고 부르며, 주로 데이터 바인딩과 관련된 처리를 실시한다

그리고 중요한 점은 디렉티브의 값이 자바스크립트 표현식이라는 점이다

<div key="id"></div> //(1)
<div v-bind:key="id"></div> //(2)

(1)과 (2) 모두 key 속성에 id라는 값을 지정하는 예 
하지만 실질적으로는 내용이 다르다

(1)의 값은 단순하게 'id'라는 문자열을 지정하는 것

(2)의 값은 'id'라는 자바스크립트 변수를 나타낸다

 

컴포넌트 지향 화면 구축

사이트의 규모가 커지면 JS, HTML, CSS 소스 코드가 난잡해 진다

Vue.js의 컴포넌트는 기능별로 자바스크립트와 템플릿을 하나의 세트로 묶어서, 다른 기능과 분리하여 개발할 수 있도록 해주는 기능

즉, HTML+CSS+JS를 세트로 만들어서 관리한다

 

 

Vue.js 설치하기

스탠드얼론(Standalone) 버전의 'Vue.js' 파일을 사용하자

개발 중에 발생하는 오류를 확인할 수 있게 개발 버전(min 파일 x)을 사용

 

스탠드얼론 버전의 Vue.js는 다운로드하거나 CDN으로 사용할 수 있다

🔽 CDN 방식

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

 

 

🗨️ 프로그램을 작성하면서 학습 내용을 배워보자

🔽 index.html 파일 생성

<!DOCTYPE html>
<html lang="en">
<body>
    <div id="app">
        <!-- 여기 #app 내부에 템플릿을 출력한다 -->
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src=min.js></script>
</body>
</html>

🔽 main.js 파일 생성

var app = new Vue({
	el: '#app'
})

new Vue({옵션}) : Vue 생성자 함수를 사용해서 Vue 인스턴스를 생성한다

 

Vue.js의 기본 기능

1) 텍스트 바인딩

🔽 html 파일

<p> {{message}} </p>

🔽 javascript 파일

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue.js'
    }
})

🔽 실제 렌더링 결과

<p>Hello Vue.js!</p>

옵션에 정의한 데이터는 다음과 같이 외부에서 접근할 수 있다

console.log(app.message) // -> Hello Vue.js!

app.data.message가 아니라 app.message라는 점에 주의

 

2) 반복 렌더링

기사 목록 또는 상품 목록과 같은 리스트는 data 옵션에 등록한 배열 또는 객체에 v-for 디렉티브를 적용해서 반복 렌더링할 수 있다

<ol>
	<li v-for="item in list">{{item}}</li>
</ol>
var app = new Vue({
    el: '#app',
    data: {
        list: ['사과', '바나나', '딸기']
    }
})

🔽 실제 렌더링 결과

<ol>
	<li>사과</li>
	<li>바나나</li>
	<li>딸기</li>
</ol>

다음 코드를 콘솔에 입력해 보면, 화면 위의 리스트에 요소가 추가되는 모습을 볼 수 있다

app.list.push('오렌지')

 

3) 이벤트 사용하기

'클릭했을 때', '선택한 요소가 변경되었을 때'처럼 DOM 이벤트 바인딩(이벤트 연결)에는 v-on 디렉티브를 사용한다

<button v-on:click="handleClick">Click</button>
var app = new Vue({
    el: '#app',
    method: {
        handleClick: function(event){
            alert(event.target) // [object HTMLButtonElement]
        }
    }
})

 

4) 입력 양식과 동기화하기

데이터와 입력 양식 입력 항목을 바인딩 할 때는 v-model 디렉티브를 사용한다

<p>{{message}}</p>
<input v-model="message">
var app = new Vue({
    el: '#app',
    data: {
        message: '초기 메시지'
    }
})

입력 양식(input)에 입력한 문자와 <p> 요소의 문자를 동기화한다

 

5) 조건 분기

v-if 디렉티브를 사용하면, 템플릿 기반의 조건 분기를 실시할 수 있다

<p v-if="show">HELLO VUE.js!</p>
var app = new Vue({
    el: '#app',
    data: {
        show: true
    }
})

다음 코드를 콘솔에 입력하면, 화면에 있는 <p> 요소가 DOM에서 제거된다

app.show = false

 

6) 트랜지션과 애니메이션

네스트 컴포넌트인 <transition> 태그를 사용하면, 템플릿 내부의 요소들에 CSS 트랜지션과 애니메이션을 손쉽게 적용할 수 있다

<button v-on:click="show=!show">변경하기</button>
<transition>
	<p v-if="show">Hello Vue.js!</p>
</transition>
var app = new Vue({
    el: '#app',
    data: {
        show: true
    }
})
.v-enter-active, .v-leave-active{
    transition: opacity 1s;
}
.v-enter, .v-leave-to{
    opacity: 0;
}

현재 예제는 페이드인 효과와 페이드아웃 효과를 적용하고 있다

 

옵션의 구성 살펴보기

기본적인 옵션 구성

var app = new Vue({
    el: '#app', // 1.마운트할 요소(선택자 형태로 지정)
    data: { // 2.어플리케이션에서 사용할 데이터(객체 또는 배열로 지정)
        message: 'Vue.js'
    },
    computed: { // 3.산출속성(함수로 인해 산출되는 데이터-리턴하는 데이터)
        computedMessage: function(){
            return this.message + '!'
        }
    },
    created: function(){ //라이프 사이클 훅(기상부터 취침까지 라이프 사이클에 따라 호출)
        //하고 싶은 처리
        /* 라이프 사이클
        	1. created : 인스턴스가 생성되는 시점(DOM 구축 전)
            2. mounted : DOM을 만든 직후
        */
    },
    methods: { //애플리케이션에서 사용할 메서드
        myMethod: function(){
            //하고 싶은 처리
        }
    }
})

 

정 리

1. Vue.js의 경우 DOM 구조 본체는 자바스크립트 데이터로 되어 있다

2. 디렉티브 값은 자바스크립트 식으로 되어있다

3. HTML 코딩을 위해 컴포넌트를 사용하면 좋다

4. 필요한 데이터와 메서드는 옵션으로 정의한다

5. new Vue()는 한 개만 만들고, 컴포넌트로 UI를 구축한다 

 

기본적인 데이터 데이터 바인딩 

리액티브 데이터는 Vue.js에서 반응하는 데이터를 의미한다(data 내용을 변경하면 화면의 UI 내용도 자동으로 변경)

var app = new Vue({
    el: '#app',
    data: {
        message: 'Vue.js' //이렇게 정의한 message는 변화를 감지할 수 있게 된다
    }
})

다음과 같이 옵션 외부에서 데이터를 정의하더라도, Vue.js 데이터로 등록하면 모두 리액티브 데이터로 변환된다

var state = { count: 0 }
var app = new Vue({
    el: '#app', // 1.마운트할 요소
    data: { // 2.어플리케이션에서 사용할 데이터
        state: state
    }
})
state.count++ //state.count는 리액티브 데이터

data 옵션 바로 아래의 속성은 이후에 따로 추가할 수 없으므로, 값이 결정되지 않은 경우라도 초깃값 또는 빈 데이터를 넣어서 정의하자

 

객체와 배열 내부의 요소 출력하기

데이터 바인딩을 할 때는 루트에 정의한 속성뿐만 아니라, '객체 내부의 속성'과 '배열의 요소'도 지정할 수 있다

var app = new Vue({
    el: '#app', 
    data: { 
        //객체 데이터
        message: {
            value: 'Hello Vue.js!'
        },
        //배열 데이터
        list: ['사과', '바나나', '딸기'],
        //다른 데이터를 사용해서 list에서 값을 추출하기 위한 요소
        num: 1
    }
})
<p>{{ message.value }}</p>        <!-- Hello Vue.js! -->
<p>{{ message.value.length }}</p> <!-- 13-->
<p>{{ list[2] }}</p>              <!-- 딸기 -->
<p>{{ list[num] }}</p>            <!-- 바나나 -->

 

표현식과 문장의 차이에 주의하기

디렉티브와 마찬가지로 Mustache에도 자바스크립트 표현식 작성이 가능하므로 다음과 같은 코드를 작성할 수 있다

{{ 1 + 1 }} //2가 출력된다

//하지만 다음 코드처럼 식이 아니라 문장을 입력해서는 안된다

{{ var foo = message }} //오류 발생

// 식이 아니라 문장을 입력하면 안된다

-- 긴 표현식은 아래와 같이 산출 속성을 이용
{{ message.length >= 10 ? '10글자 이상', '10글자 미만'}}

 

TIP : 데이터의 내용 확인하기

템플릿에 다음과 같이 태그를 작성하면, 현재 데이터 전체의 상태가 어떤지 JSON 형식으로 화면에 출력할 수 있다

<pre>{{ $data }}</pre>

 

클릭으로 카운터의 수 늘리기

v-on 디렉티브를 사용해서 버튼이 클릭될 때 increment라는 이름의 메서드가 호출되게 하자

<div id="app">
	<!-- count 속성 출력하기 -->
    <p>{{ count }}번 클릭했습니다.</p>
    
    <!-- 이 버튼을 클릭하면 increment 메서드가 호출된다 -->
    <button v-on:click="increment">카운트 하기</button>
</div>
var app = new Vue({
    el: '#app', 
    data: { 
        count : 0
    },
    methods: {
        //버튼을 클릭할 때의 핸들러
        increment: function(){
            this.count += 1 //다시 할당하는 처리만 한다 
            //메서드 내부에서는 this를 붙여야지 data에 접근이 가능하다
        }
    }
})

 

클래스와 스타일 데이터 바인딩

new Vue({
    el: '#app', 
    data: { 
        isChild: true,
        isActive: true,
        textColor: 'red',
        bgColor: 'lightgray'
    }
})
<p class="child" v-bind:class=" { 'is-active' : isActive }">Text</p>
<p style="color:blue" v-bind:style="{ color : textColor }">Text</p>

실제 렌더링 결과(데이터 바인딩을 하지 않은 플레인 속성과 함께 사용하는 경우, 바인딩한 것이 덮어쓰게 된다)

<p class="child is-active">Text</p>
<p style="color:red" >Text</p>

 

객체 데이터 전달하기

템플릿에 여러 개의 클래스 또는 스타일을 모두 적으면 코드의 가독성이 굉장히 떨어진다

따라서 data 객체에 객체를 정의한 뒤 전달하는 것이 좋다

<p v-bind:class="classObject">Text</p>
<p v-bind:style="styleObject">Text</p>
new Vue({
    el: '#app', 
    data: { 
        classObject: {
            child: true,
            'is-active': false
        },
        styleObject: {
            color: 'red',
            backgroundColor: 'lightgray'
        }
    }
})

이렇게 작성하면 코드가 굉장히 깔끔해진다 🙌

 

여러 개의 속성 데이터 바인딩하기

대량의 속성을 각각의 속성에 바인딩하면 가독성이 크게 떨어진다

new Vue({
    el: '#app', 
    data: { 
        item: {
            id: 1,
            src: 'item1.jpg',
            alt: '상품1의 섬네일',
            width: 200,
            height: 200
        }
    }
})

안좋은 예시(가독성 떨어짐)

<img v-bind:src="item.src" v-bind:alt="item.alt"
     v-bind:width="item.width" v-bind:height="item.height">

좋은 예시(가독성 좋고 심플함)

<img v-bind="item">

또는 추가로 변현해서 사용 가능(특정 요소만 따로 지정)

<img v-bind="item" v-bind:id="'thumb-'+item.id">

 

SVG 데이터 바인딩하기

vue.js는 SVG의 DOM도 HTML과 같은 방법으로 데이터 바인딩할 수 있다

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="100" cy="75" v-bind:r="radius" fill="lightpink"/>
</svg>
<input type="range" min="0" max="100" v-model="radius">
new Vue({
    el: '#app', 
    data: { 
        radius: 50
    }
})

코드 실행 결과값(아주 쉽게 멋진 UI 조작과 움직이는 그래프 등을 구현할 수 있다)

 

템플릿에서 조건 분기하기

Vue.js는 템플릿에서 조건 분기를 할 수도 있으며, v-if와 v-show 디렉티브는 적용한 요소의 출력 여부를 바꾼다

<div v-if="ok">v-if 조건으로 출력하기</div> <!-- 주석으로 처리 -->
<div v-show="ok">v-show 조건으로 출력하기</div> <!-- display : none -->
new Vue({
    el: '#app', 
    data: { 
        ok: false
    }
})

모두 ok 속성의 값이 true일 때만 <div> 요소를 출력한다(변경 빈도가 높은 경우에는 v-show를 사용하자)

 

<template> 태그를 사용한 v-if 그룹

여러 요소를 if 처리할 때 사용(v-show로는 사용할 수 없다)

<template v-if="ok">
	<header>타이틀</header>
	<div>콘텐츠</div>
</template>

 

v-else-if와 v-else로 그룹 만들기

조합해서 그룹으로 만들면 여러 개의 조건을 지정할 수 잇다(v-show로는 사용할 수 없다)

<div v-if="type === 'A'">
	type는 A
</div>
<div v-else-if="type === B">
	type는 B
</div>
<div v-else>
	모든 조건을 만족하지 않는 경우
</div>

⭐ 하지만 위 경우 속성의 상태가 남거나 트랜지션이 일어나지 않는 등 예상하지 못한 문제가 발생할 수 있다

이러한 경우에는 각각의 요소에 유니크한 key를 설정해 문제를 해결할 수 있다

 

v-else-if, v-else와 key

<!-- 두 개의 div가 다른 요소라는 것을 명시적으로 지정하기 -->
<div v-if="loaded" key="content-visible">
	content
</div>
<div v-else key="content-loading">
	loading now...
</div>

 

리스트 데이터 출력/변경하기

이번에는 몬스터 정보가 들어있는 배열을 사용해서 설명하겠다

[
	{id : 1, name : '슬라임', hp : 100},
	{id : 2, name : '고블린', hp : 200},
	{id : 3, name : '드래곤', hp : 500},
]

이렇게 유니크 키가 있으면 가상 DOM으로 렌더링할 때 최적화가 이루어진다

 

요소를 반복해서 렌더링하기

반복해서 렌더링하고 싶은 태그에 v-for 디렉티브를 적용한다

<li v-for="<각 요소를 할당할 변수 이름> in <반복 대상 배열 또는 객체>">

⭐ 아래와 같이 사용하면 된다

<div id="app">
	<ul>
		<li v-for="item in list" v-bind:key="item.id">
			ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
		</li>
	</ul>
</div>
<li v-for="<각 요소를 할당할 변수 이름> in <반복 대상 배열 또는 객체>">
new Vue({
    el: '#app', 
    data: { 
        list : [
            {id : 1, name : '슬라임', hp : 100},
            {id : 2, name : '고블린', hp : 200},
            {id : 3, name : '드래곤', hp : 500},
        ]
    }
})

실제 렌더링 결과

<div id="app">
	<ul>
		<li>ID.1 슬라임 HP.100</li>
		<li>ID.2 고블린 HP.200</li>
		<li>ID.3 드래곤 HP.500</li>
	</ul>
</div>

반복 변수에는 인덱스가 아니라 요소 자체가 들어간다

 

인덱스와 객체 키 사용하기

변수 부분을 괄호로 감사면 배열의 인덱스도 받을 수 있다

<li v-for="(item, index) in list">...</li>

객체의 경우 '<값><키><인덱스>' 순서이므로 주의해야 한다

<li v-for="(item, key, index) in list">...</li>

 

키의 역할

키의 지정 여부에 따라 리스트를 조작할 때 큰 차이가 발생한다

 - 키가 있는 경우 : 삭제된 key의 DOM만 제거된다

 - 키가 없는 경우 : 요소 전체를 변경한다

 

KEY="1"처럼 문자열을 지정할 수도 있지만, 반복으로 모두 같은 '1'이 지정되어 버리면 아무 의미가 없다(유니크한 속성이 필요)

 

조건을 사용해서 클래스 조작하기

예제 1) hp 속성이 '300'보다 큰 몬스터만 .strong 클래스를 적용하고, '강하다!'라는 문자를 출력하도록 만들자

<div id="app">
	<ul>
		<li v-for="item in list" v-bind:key="item.id" v-bind:class="{ strong:item.hp > 300 }">
			ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
            	<span v-if="item.hp > 300">강하다!</span>
		</li>
	</ul>
</div>
<li v-for="<각 요소를 할당할 변수 이름> in <반복 대상 배열 또는 객체>">

실제 렌더링 결과

<div id="app">
	<ul>
		<li>ID.1 슬라임 HP.100</li>
		<li>ID.2 고블린 HP.200</li>
		<li class="strong">ID.3 드래곤 HP.500<span>강하다!</span></li>
	</ul>
</div>

 

예제 2) v-if를 적용해서, hp 속성이 '300'보다 작은 몬스터만 렌더링하도록 만들어보자

<ul>
    <li v-for="item in list" v-bind:key="item.id" v-if="item.hp < 300">
        ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
            <span v-if="item.hp > 300">강하다!</span>
    </li>
</ul>

실제 렌더링 결과

<div id="app">
	<ul>
		<li>ID.1 슬라임 HP.100</li>
		<li>ID.2 고블린 HP.200</li>
	</ul>
</div>

 

리스트 변경하기

리스트 요소 변경도 일반적인 자바스크립트에서 배열 또는 객체를 변경할 때와 크게 다르지 않다

 

리스트에 요소 추가하기

리스트에 새로운 요소를 추가하려면 배열의 push나 unshift를 사용한다

this.list.push(<새로운 값>)

예제 1) '몬스터 추가' 버튼을 만들고 이벤트를 핸들링한다

<!-- 입력 양식의 입력 값을 새로운 몬스터의 이름으로 사용하기 -->
이름 <input v-model="name">
<button v-on:click="doAdd">몬스터 추가하기</button>
<ul>
	<li v-for="item in list" v-bind:key="item.id">
		ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
	</li>
</ul>
new Vue({
    el: '#app', 
    data: { 
        list : [
            {id : 1, name : '슬라임', hp : 100},
            {id : 2, name : '고블린', hp : 200},
            {id : 3, name : '드래곤', hp : 500},
        ]
    },
    methods: {
        //추가 버튼을 클릭했을 때의 핸들러
        doAdd: function(){
            //리스트 내부에서 가장 큰 ID 추출하기
            var max = this.list.reduce(function(a, b){
                return a > b.id ? a : b.id
            }, 0)

            //새로운 몬스터를 리스트에 추가하기
            this.list.push({
                id: max + 1, //현재 최대 ID에 1을 더해서 유니크 ID로 사용하기
                name: this.name, //현재 입력 양식의 값
                hp: 500
            })
        }
    }
})

 

예제 2) '몬스터 제거' 버튼을 만들고 이벤트를 핸들링한다

<!-- 입력 양식의 입력 값을 새로운 몬스터의 이름으로 사용하기 -->
이름 <input v-model="name">
<ul>
    <li v-for="(item, index) in list" v-bind:key="item.id">
        ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
        <button v-on:click="doRemove(index)">몬스터 제거하기</button>
    </li>
</ul>
new Vue({
    el: '#app', 
    data: { 
        list : [
            {id : 1, name : '슬라임', hp : 100},
            {id : 2, name : '고블린', hp : 200},
            {id : 3, name : '드래곤', hp : 500},
        ]
    },
    methods: {
        //제거 버튼을 클릭했을 때의 핸들러
        doRemove: function(index){
            // 전달받은 인덱스 위치에서 한 개만큼 제거하기
            this.list.splice(index, 1)
        }
    }
})

 

리스트 요소 변경하기

예를 들어서 몬스터 이름 또는 HP를 모두 변경하고 싶을 수 있다

this.list[0] = {id : 1, name: '대왕 슬라임', hp: 500}

하지만 이렇게 하면 안된다(Vue.js에서는 다른 방식을 사용해야 한다)

현재 시점에서 Vue.js는 이처럼 인덱스 숫자를 사용한 배열 요소 변경을 감지하지 못하기 때문이다

 

이를 구하려면 전력 API인 Vue.set 메서드를 사용해야 한다(this.$set라는 별칭 이용)

this.$set(<변경할 데이터>, <인덱스 또는 키>, <새로운 값>)

this.$set(this.list, 0, {id: 1, name: '대왕 슬라임', hp: 500})

 

리스트 요소 속성 변경하기

예제 1) 공격 버튼 클릭할 때 마다 몬스터의 HP를 '10'씩 줄이도록 한다

제거 버튼과 마찬가지로 배열의 인덱스를 매개변수로 전달한다

<ul>
	<li v-for="(item, index) in list" v-bind:key="item.id" v-if="item.hp">
		ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
        <span v-if="item.hp < 50">큰 피해...!</span>
        <button v-on:click="doAttack(index)">공격하기</button>
	</li>
</ul>
new Vue({
    el: '#app', 
    data: { 
        list : [
            {id : 1, name : '슬라임', hp : 100},
            {id : 2, name : '고블린', hp : 200},
            {id : 3, name : '드래곤', hp : 500},
        ]
    },
    methods: {
        //제거 버튼을 클릭했을 때의 핸들러
        doAttack: function(index){
            this.list[index].hp -= 10 //HP 감소시키기
        }
    }
})

 

유니크 키가 없는 배열은 쓰지 말라는 것이 아니다(단순하게 출력용으로는 사용해도 괜찮다)

 

리터럴에 직접 v-for 적용하기

<span v-for="item in 15">{{ item }}</span> //1부터 15출력

<span v-for="item in [1, 5, 10, 15]">{{ item }}</span> //1, 5, 10, 15 출력



--------------------------------------------------------------------------

<span v-for="item in text">{{ item }}</span> //V , U, E 출력

new Vue({
	el: '#app',
    data: {
    	text: 'Vue'
    }
})

이를 활용하면 다양한 텍스트 애니메이션을 만들 수 있다

 

⭐ 외부에서 데이터 가져와서 출력하기

JSON 파일 또는 웹 API를 사용해서 가져와야 한다

여기서는 Ajax 라이브러리 💁‍♂️'axios'를 사용한다(드디어 Vue.js 프론트엔드 <-> SpringBoot 백엔드 통신 기초 학습)

 

🔽 list.json(임시 파일)

[
	{"id" : 1, "name" : "슬라임", "hp" : 100},
	{"id" : 2, "name" : "고블린", "hp" : 200},
	{"id" : 3, "name" : "드래곤", "hp" : 500}    
]

특정 시점에서 자동으로 처리가 일어나게 하려면 라이프 사이클 훅을 사용하자.

인스턴스가 생성될 때 곧바로 데이터를 가져올 것이라면 created를 사용하는 것이 적당하다

<ul>
	<li v-for="(item, index) in list" v-bind:key="item.id">
		ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
	</li>
</ul>
new Vue({
    el: '#app', 
    data: { 
        //미리 빈 리스트 준비하기
        list: []
    },
    created: function(){
        axios.get('list.json').then(function(response){
            //데이터를 읽어 들였다면 list에 할당하기
            this.list = response.data
        }.bind(this)).catch(function(e){
            console.error(e);
        })
    }
})

list 속성은 리액티브 데이터이므로 응답을 맏아 데이터를 대입하는 시점에 화면에 있는 리스트도 변경이 된다

하지만 응답이 늦을 경우, 아무것도 출력이 되지 않으므로 로딩 애니메이션 등을 넣는 것이 좋다

 

통신으로 외부 데이터를 사용하면 조금 더 본격적인 프로그램을 만들 수 있다(지금은 단순하게 샘플 - 동작X)

 

 

DOM을 직접 참조하는 $el과 $refs

데이터 바인딩 덕분에 DOM에 직접 접근하지 않아도 내용을 변경할 수 있다

하지만 상황(요소의 위치와 높이 파악 필요 등)에 따라서 직접 DOM 접근이 필요한데, 이 때 $el과 $refs를 사용한다

 

이 두가지 속성은 DOM을 참조해야 하므로, 라이프 사이클 중 mounted 이후 부터 사용 가능하다

 

$el의 사용 방법

컴포넌트 템플릿을 감싸고 있는 루트 요소는 $el(element의 약어)을 사용해서 DOM을 직접 참조할 수 있다

 

new Vue({
    el: '#app', 
    mounted: function(){
        console.log(this.$el) // -> <div id="app"></div>
    }
})

$ref의 사용 방법

루트 이외의 요소는 특별한 속성 ref와 $refs를 사용해서 참조할 수 있다

일단 템플릿에서 대상 요소에 ref 속성을 지정하고 이름을 붙여 준다

<div id="app">
	<p ref="hello">Hello</p>
</div>

이렇게 지정한 요소는 인스턴스 메서드 내부에서 다음과 같이 접근할 수 있다

new Vue({
    el: '#app', 
    mounted: function(){
        console.log(this.$refs.hello) // -> p요소를 DOM으로 다룰 수 있다
    }
})

 

 

템플릿 제어 디렉티브

디렉티브 설명
v-pre 템플릿 컴파일 생략하기
v-once 한 번만 바인딩하기 
v-text Mustache 대신 텍스트 콘텐츠로 렌더링하기
v-html HTML 태그를 그대로 렌더링하기
v-cloak 인스턴스 준비가 끝나면 제거하기

 

🔽 v-pre

HTML을 컴파일하지 않고, 정적 콘텐츠로 다룰 때 사용한다

<a v-bind:href="url" v-pre>
	Hello {{ message }}
</a>

Mustache와 디렉티브 등이 그대로 출력

<a v-bind:href="url">Hello {{ message }}</a>

서버 사이드 렌더링 때 XSS를 막기 위한 용도 등으로 사용한다

 

🔽 v-once

v-once 디렉티브는 템플릿을 한 번만 컴파일하고 이후에는 정적 콘첸츠로 다루고 싶을 때 사용한다

<a v-bind:href="url" v-once>
	Hello {{ message }}
</a>

한 번만 다음과 같이 렌더링되며, 이후에는 변경되지 않음

 

 

⭐정 리

1) 사용하고 싶은 데이터는 data 옵션에 등록한다

2) 리스트를 사용할 경우 유니크한 key를 적는 것이 좋다

3) 배열 인덱스를 사용한 변경은 Vue.set을 이용한다

4) 함수 호출 방법에 따라 this가 변화할 수 있다

5) $el, $refs는 mounted 이후부터 사용할 수 있다

 

 

 

 

 

💁‍♂️

🔽