[Vue #1] 뷰 시작하기

최훈오·2023년 11월 20일

데브코스

목록 보기
16/29
post-thumbnail

Vue란?

기존의 바닐라 자바스크립트나 Jquery로 개발하는 방식과는 달리 자동으로 데이터가 변하면 DOM 요소도 자동으로 바뀌게 해주는 반응형 데이터를 만드는 아주 유용한 프레임워크이다.

	<head>
		<title>Document</title>
		<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
	</head>
	<body>
		<div id="app">
			<h1>{{msg}}</h1>
		</div>

		<script>
			const App = {
				data() {
					return {
						msg: "Hello Vue!",
					};
				},
			};
			const app = Vue.createApp(App);
			const vm = app.mount("#app");
		</script>
	</body>

기본적인 코드 형식이다.

App 이라는 view Application을 DOM 요소인 #appmount(연결) 시키면 데이터가 변하면 DOM요소도 자동으로 변한다.

라이프사이클

<html lang="en">
	<head>
		<title>Document</title>
		<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
	</head>
	<body>
		<div id="app">
			<h1>{{msg}}</h1>
		</div>

		<script>
			const App = {
				data() {
					return {
						msg: "Hello Vue!",
					};
				},
				//  view application이 만들어지기 직전
				beforeCreate() {
					console.log("beforeCreate!");
				},
				//   view application이 만들어지기 직후
				created() {
					console.log("created!");
				},
				//   view application이 html과 연결되기 직전
				beforeMount() {
					console.log("beforeMount!");
				},
				//   view application이 html과 연결되기 직후
				mounted() {
					console.log("mounted!");
				},
			};
			const app = Vue.createApp(App);
			const vm = app.mount("#app");
		</script>
	</body>
</html>

라이프사이클은 크게 여덟가지로 나뉘고 자주 사용하는 라이프사이클 메서드는 createdmounted이고, 그 외의 메서드는 활용도가 매우 떨어진다.

beforeCreate

view application이 만들어지기 직전 실행되는 함수

created

view application이 만들어지기 직후 실행되는 함수

beforeMount

view application이 html과 연결되기 직전 실행되는 함수

mounted

view application이 html과 연결되기 직후 실행되는 함수

beforeUpdate

데이터가 업데이트 되기 직전 실행되는 함수

updated

데이터가 업데이트 되기 직후 실행되는 함수

beforeUpdate와의 차이점은 데이터가 아니라 DOM 요소**이다.
즉, 데이터는 같이 업데이트 되었더라도 DOM에 반영이 되어있음을 기점으로 두 메서드는 나뉜다.

beforeUnmount

view application이 html과 연결해제 직전 실행되는 함수

unmounted

view application이 html과 연결해제 직후 실행되는 함수

뭘 사용하지?

우선적으로 created를 사용해보고, 이것으로 처리를 하지 못한다면 mounted를 고려하는 방향이 바람직하다.

템플릿 문법

보간법

데이터를 이중 중괄호 구문으로 출력한다.

<span>메시지: {{ msg }} </span>

속성

이중 중괄호 구문은 기본적으로 html 속성에 사용할 수 없기 때문에 v-bind를 이용하여야 한다.

<div v-bind:id="dynamicId"></div>

리액트와 동일하게 각 바인딩은 하나의 단일 표현식만 포함해야 한다. 즉, 조건문은 작동하지 않고 삼항 연산자를 사용해야 한다.

	<body>
		<style>
			.active {
				color: red;
			}
		</style>
		<div id="app">
			<h1 v-bind:class="name">Hello Vue!</h1>
		</div>

		<script>
			const App = {
				data() {
					return {
						name: "active",
					};
				},
			};
			Vue.createApp(App).mount("#app");
		</script>
	</body>

문자열 외에도 truthy or falsy값을 전달할 수 있다.

		<div id="app">
			<input type="text" value="Hello Vue!" v-bind:disabled="disabled" />
		</div>

		<script>
			const App = {
				data() {
					return {
						disabled: false,
					};
				},
			};
			Vue.createApp(App).mount("#app");
		</script>

디렉티브

v-로 시작하는 특수한 속성이다.

  • v-if : 표현식 값의 참, 거짓 여부를 바탕으로 엘리먼트를 삽입하거나 제거한다.

    <p v-if="seen">ㅎㅎ</p>
  • v-bind: 반응적으로 html 속성을 갱신하는데 사용하며 일부 디렉티브는 디렉티브명 뒤에 : 으로 표기되는 전달인자를 가진다.

    <a v-bind:href="url">ㅎㅎ</a>

    여기서 href는 전달인자로 v-bind 디렉티브를 통해 표현식 url의 값을 href속성에 바인딩 한다.

  • v-on : DOM 이벤트를 수신하는 역할을 한다.

    <a v-on:click="doSomething">ㅎㅎ</a>

    전달인자로는 수신할 이벤트명이 들어가게 된다.

자바스크립트 표현식을 대괄호로 묶어서 동적전달인자로도 사용 가능하다.

약어

가장 자주 사용되는 두 디렉티브 v-bindv-on에 대해 약어를 제공한다.

<a :href="url">ㅎㅎ</a>

v-bind: 대신에 :를 사용할 수 있다.

<a @click="doSomething">ㅎㅎ</a>

v-on: 대신에 @를 사용할 수 있다.

Data

데이터는 함수여야 한다.

const App = {
  data() {
    return {
      
    }
  }
}

뷰의 구조는 위와 같이 함수로 작성되어 있는데 데이터 불변성을 지키기 위해서이다. 만약 객체로 작성된다면 참조 타입이므로 중간에 값이 바뀌어버리면 원본 값이 바뀌어 재사용할 수가 없기 때문이다.

반응성을 유지하려면 데이터 옵션에 미리 선언해 놔야 한다.

	<body>
		<div id="app">
			<h1>{{count}}</h1>
			<h2>{{double}}</h2>
		</div>

		<script>
			const App = {
				data() {
					return {
						count: 0,
					};
				},
			};
			const vm = Vue.createApp(App).mount("#app");
		</script>
	</body>

count값은 미리 선언해놔서 반응성을 띄지만 double값은 미리 선언해 놓지 않아서 브라우저의 개발자 도구를 통해 값을 선언해도 화면에 보여지지 않는다.

프록시

html요소와 연결된 view 어플리케이션을 콘솔에 출력해보면 proxy요소를 볼 수 있다.

특정 데이터가 언제 조회가 되는지 언제 할당이 되는지 감시하여 그 중간에서 특정한 로직을 수행할 수 있게 한다.

프록시가 어떻게 구현되는지 알아보자.

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Document</title>
	</head>
	<body>
		<script>
			const app = {
				data() {
					return {
						count: 0,
					};
				},
			};

			// 감시할 target객체, handler함수
			const proxyA = new Proxy(app.data(), {
				get(target, key) {
					return target[key];
				},
				set(target, key, value) {
					target[key] = value;
				},
			});
		</script>
	</body>
</html>

Proxy 생성자 함수를 통해 감시할 객체, handler함수를 정의하면 그 객체의 값에 접근할때는 get 함수가 호출되고, 할당할때는 set함수가 호출된다.

따라서 프록시가 중간에 반응형 데이터의 변화를 감지하여 중간에 가로채서 로직을 실행한 후에 화면에 그리는 반응형 데이터를 구현하는 것이다.

또한 여러개의 프록시를 만들어 하나의 객체를 감지하여도 데이터는 함수로 반환되기 때문에 각각 데이터 불변성을 유지하여 고유한 데이터를 가질 수 있다.

Methods

컴포넌트 인스턴스에 메서드를 추가하려면 methods옵션을 사용한다.

const app = Vue.createApp({
  data() {
    return { count: 4 }
  },
  methods:{
    increment() {
      this.count++
    }
  }
})

const vm = app.mount('#app')
vm.increment() // 4
console.log(vm.count) // 5

정의된 함수 안에서는 this키워드를 사용하여 정의된 데이터에 접근이 가능하다.

함수를 정의할 때는 올바른 this 바인딩을 위해 화살표 함수는 당연히 사용하면 안된다.

만약 특정 태그에 함수를 연결하려면 다음과 같이 작성하면 된다.

<button @click="increment">Up vote</button>

이벤트에다 메서드를 집어넣을 때는 위와 같이 작성하면 된다.

<span :title="toTitleDate(date)">
  {{ formatDate(date) }}
</span>

하지만 v-bind를 통해 표현식을 사용할 때는 소괄호를 이용해야 한다는 점이 있다.

마치며

올해 초, 처음 프론트 공부를 시작했을 때 패캠에서 영웅님 뷰 강의를 들었던 기억이 난다.

그때 반 정도 듣다가 도저히 이해가 가지 않았었다.
이러한 이유로 뷰 공포증이 있었는데 이번엔 이해가 무난하게 돼서 다행이다.

본질적으로 컴포넌트 방식으로 렌더링 하는 것은 맞는데 jsx 문법에 익숙해진 나에게 문법 자체는 겉으로 보기에는 더 복잡해 보이지만 오히려 리액트보다 러닝커브가 훨씬 낮은 느낌?을 받았다.

프레임워크나 라이브러리를 처음 배우는데 특정 서비스를 빠르게 만들어야 할 때는 Vue가 유용하게 느껴질듯??

0개의 댓글