2019년에 Vue로 토이 프로젝트를 진행한 후, 이후로는 React를 쭉 사용해왔는데 최근에 새로운 프로젝트에서 Vue를 사용해서 Vue에 대한 공부를 시작했다.
Vue와 React는 많은 유사점이 있지만, 각각의 특성과 문법적인 차이들이 있다. 나는 기존 SPA 지식을 바탕으로 빠르게 Vue를 익혀 실무에 투입 하고자한다.
새로 투입할 프로젝트가 신규프로젝트가 아니라 vue3가 아닌 vue2를 사용한다.(심지어 타입스크립트도 사용하지 않는다..🥲)
최근에 나온 강의들은 대부분 vue3 강의여서 vue2 강의 찾기가 까다로웠다.
관련해서 여러 서칭을 하다가 트렐로 개발로 배우는 Vuejs, Vuex, Vue-Router 프론트엔드 실전 기술을 듣기로 결정했다.
(예전에 김정환님의 실습 UI 개발로 배워보는 순수 javascript 와 VueJS 개발 라는 강의가 MVC 패턴과 MVVM패턴을 이해하는데 많은 도움이 됐어서 망설임 없이 선택했다.)
npm install -g vue-cli
vue init 프로젝트이름
data
옵션은 Vue 인스턴스에서 사용할 데이터를 정의하는 객체이다. 이 데이터는 뷰 템플릿에서 사용되며, 변경되면 화면이 자동으로 업데이트된다.
예시
<div id="app">
<p>{{ message }}</p>
</div>
export default {
data() {
return {
message: '안녕, Vue!'
}
}
}
react에서 비슷한 개념
state
computed
옵션은 기존의 데이터를 가공하거나 연산하여 새로운 값을 계산하는 속성이다. data
와 달리, 의존하는 데이터가 변경될 때만 다시 계산된다.
예시
<div id="app">
<p>{{ message }}</p>
<p>{{ reversedMessage }}</p>
</div>
const app = new Vue({
el: '#app',
data: {
message: 'Vue로 배우는',
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
});
react에서 비슷한 개념
useMemo
methods
옵션은 Vue 인스턴스에서 사용할 메서드를 정의하는 객체이다. 이 메서드들은 뷰 템플릿에서 호출할 수 있다.
예시
<div id="app">
<button v-on:click="sayHello">인사하기</button>
</div>
const app = new Vue({
el: '#app',
methods: {
sayHello() {
alert('안녕하세요!');
}
}
});
watch
옵션은 데이터의 변경을 감시하고, 해당 데이터가 변경될 때 특정 로직을 실행할 수 있다.
예시
<div id="app">
<p>{{ message }}</p>
</div>
const app = new Vue({
el: '#app',
data: {
message: 'Vue를 배우자!',
},
watch: {
message(newVal, oldVal) {
console.log('메시지가 변경되었습니다:', newVal, oldVal);
}
}
});
wath와 computed와 차이점
watch
는 데이터의 변화를 감시하고 추가적인 로직을 수행할 때 사용되며, computed
는 데이터의 가공이나 연산 결과를 계산하여 사용할 때 사용된다.
react에서 비슷한 개념
useEffect
created
와 mounted
는 라이프사이클 훅으로, Vue 인스턴스의 생성과 DOM 요소와의 연결을 다룬다. created
는 인스턴스가 생성된 후에 호출되는데, 이때 데이터 초기화 등의 로직을 수행할 수 있다. mounted
는 인스턴스가 DOM에 부착된 후에 호출되는데, 이때 외부 라이브러리와의 연동이나 비동기 작업 등을 처리할 수 있다.
예시
<div id="app">
<p>{{ message }}</p>
</div>
const app = new Vue({
el: '#app',
data: {
message: 'Vue로 웹 앱 만들기!',
},
created() {
console.log('Vue 인스턴스가 생성되었습니다.');
},
mounted() {
console.log('Vue 인스턴스가 DOM에 부착되었습니다.');
}
});
updated
훅은 Vue 컴포넌트의 뷰가 다시 렌더링되고 화면이 업데이트된 후에 호출되는 라이프사이클 훅이다. 이 훅은 컴포넌트가 업데이트된 후에 추가적인 작업을 수행하거나, DOM을 조작하거나, 외부 라이브러리와의 상호작용을 처리하는 데 유용하다.
예시
<template>
<div>
<input v-model="message" ref="inputField" type="text">
</div>
</template>
<script>
export default {
data() {
return {
message: '안녕하세요, Vue!',
};
},
updated() {
// 컴포넌트가 업데이트되고 나서 실행됨
// 입력 요소의 값을 변경한 후 포커스를 설정함
this.$refs.inputField.focus();
},
};
</script>
react에서 비슷한 개념
useEffect(() => {
// 컴포넌트가 업데이트된 후 실행됨
// 추가적인 작업 수행
if (inputRef.current) {
inputRef.current.focus();
}
});
v-model
은 양방향 데이터 바인딩을 위한 디렉티브로, 사용자 입력을 즉시 반영하고, 반대로 데이터 변경이 입력 요소에도 즉시 반영된다.
예시
<div id="app">
<input v-model="message" type="text">
<p>{{ message }}</p>
</div>
const app = new Vue({
el: '#app',
data: {
message: '입력 값을 바꿔보세요!',
}
});
props
는 부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하기 위해 사용되는 속성이다. 자식 컴포넌트에서는 props
로 받은 데이터를 변경할 수 없다. 데이터 변경이 필요한 경우 emit
을 사용하여 이벤트를 발생시키고, 부모 컴포넌트에서 이벤트를 처리할 수 있다.
예시
<!-- 부모 컴포넌트 -->
<div id="app">
<child-component :message="parentMessage" @childEvent="handleChildEvent"></child-component>
</div>
// 자식 컴포넌트
Vue.component('child-component', {
props: ['message'],
template: `
<div>
<p>{{ message }}</p>
<button @click="emitEvent">자식 컴포넌트 이벤트 발생</button>
</div>
`,
methods: {
emitEvent() {
this.$emit('childEvent', '자식 컴포넌트에서 이벤트 발생!');
}
}
});
const app = new Vue({
el: '#app',
data: {
parentMessage: '부모 컴포넌트로부터 데이터 전달',
},
methods: {
handleChildEvent(message) {
alert('부모 컴포넌트에서 이벤트 처리: ' + message);
}
}
});
npm install vue-router
// router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
// Vue.use를 사용하여 Vue Router를 전역으로 등록합니다.
Vue.use(VueRouter);
// 라우트 컴포넌트를 가져옵니다.
import Home from './components/Home.vue';
import About from './components/About.vue';
// 라우트 정의
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
];
// 라우터 인스턴스 생성
export default new VueRouter({
routes,
});
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
el: '#app',
router,
render: h => h(App)
})
<template>
<div>
<router-link to="/">홈</router-link>
<router-link to="/about">소개</router-link>
<router-view></router-view>
</div>
</template>
npm install vuex
import Vue from 'vue';
import Vuex from 'vuex';
// Vue.use를 사용하여 Vuex를 전역으로 등록합니다.
Vue.use(Vuex);
// 상태(state) 정의
const state = {
count: 0,
};
// 변이(mutations) 정의
const mutations = {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
},
};
// 액션(actions) 정의
const actions = {
increment(context) {
context.commit('increment');
},
decrement(context) {
context.commit('decrement');
},
};
// Vuex 스토어 생성
const store = new Vuex.Store({
state,
mutations,
actions,
});
export default store;
mutation과 action의 차이
mutation
은 동기적인 상태 변경을 다루는 반면에 action
은 비동기적인 작업과 상태 변경을 다룬다. 비동기 작업을 처리해야 할 때 action
을 사용하고, 상태를 동기적으로 변경해야 할 때 mutation
을 사용하는 것이 일반적인 패턴이다.
mapState
와 mapActions
를 활용하면 Vuex의 상태와 액션을 더 직관적이고 간결하게 컴포넌트 내에서 사용할 수 있다. 이를 통해 코드 가독성을 높이고 반복적인 작업을 줄일 수 있다.
<template>
<div>
<p>카운트: {{ count }}</p>
<button @click="increment">증가</button>
<button @click="decrement">감소</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: mapState(['count']),
methods: mapActions(['increment', 'decrement']),
};
</script>