Table of Contents

Vue.js

starting vue.js

Vue.js 다운로드

Install Vue.js

  1. Vue CLI 설치
    $ npm install -g @vue/cli
    # or
    $ yarn global add @vue/cli
    # or
    $ yarn dlx @vue/clie
    
    $ vue --version   # 확인
    $ npm list -g --depth=0   # npm 설치 리스트 확인
    </shx>
      - Vue CLI 삭제 <sxh bash>
    $ npm uninstall -g vue-cli
    
  2. vue 프로젝트 생성
    $ vue create <프로젝트 이름>
    
    $ cd <프로젝트 이름>
    $ npm run serve
    
  3. vuetify 패키지 추가
    $ vue add vuetify
    
  4. vue-router 설치
    $ vue add router
    </bash>
      - vuex 설치 <sxh bash>
    $ vue add vuex
    
  5. axios 설치
    $ vue add axios
    

Getting Started

CDN 이용
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- production version, optimized for size and speed -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

Vue.js 기본 구조

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <title>Vue.js App</title>
  <link href="main.css" rel="stylesheet">
</head>
<body>
  <div id="app">
    <!-- template 출력 --> 
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script src="main.js"></script>
</body>
</html>
var app = new Vue({
  el: '#app'
})

기본 기능

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})    
<p>{{ message }}</p>

Options in Vue Objects

var app = new Vue({

  // el
  el: '#app',
  
  // data
  data: {
    message: 'Vue.js'
  },
  
  // computed
  computed: {
    computedMessage: function() {
      return this.message + '!'
    }
  },
  
  // lifecycle hooks
  created: function() {
    // something to what you do
  },
  
  // methods
  methods: {
    myMethod: function() {
      // something to what you do
    }
  }

})

Lifecycles
Methods Timing
beforeCreate 인스턴스가 생성되고, 리액티브 초기화가 일어나기 전
created 인스턴스가 생성되고, 리액티브 초기화가 일어난 후
beforeMount 인스턴스가 마운트되기 전
mounted 인스턴스가 마운트된 후
beforeUpdate 데이터가 변경되어 DOM에 적용되기 전
updated 데이터가 변경되어 DOM에 적용된 후
beforeDestroy Vue 인스턴스가 제거되기 전
destroyed Vue 인스턴스가 제거된 후
errorCaptured 임의의 자식 컴포넌트에서 오류가 발생했을 때

Data Binding

v-bind 장식자
장식자 의미
.prop 속성 대신에 DOM 속성으로 바인딩, DOM 속성과 직접 바인딩
.camel 케밥케이스1) 속성 이름을 카멜 케이스로 변환
.sync 양방 바인딩
템플렛 제어 디렉티브
디렉티브 설명
v-pre 템플릿 컴파일 생략
v-once 한 번만 바인딩
v-text Mustache 대신 텍스트 콘텐츠로 렌더링
v-html HTML 태그를 그대로 렌더링
v-cloak 인스턴스 준비가 끝나면 제거

Event Handling

이벤트 장식자
장식자 설명
.stop event.stopPropagation()을 호출
.prevent event.preventDefault()를 호출
.capture 캡처 모드로 DOM 이벤트를 핸들
.self 이벤트가 해당 요소에서 직접 발생할 때만 핸들러를 호출
.native 컴포넌트의 루트 요소 위에 있는 네이티브 이벤트를 핸들
.once 한 번만 핸들
.passive {passive: true}로 DOM 이벤트를 핸들
클릭 이벤트
장식자 설명
.left 마우스 왼쪽 버튼으로 눌렀을 때만 핸들러 호출
.right 마우스 오른쪽 버튼으로 눌렀을 때만 핸들러 호출
.middle 마우스 중간 버튼으로 눌렀을 때만 핸들러 호출
키 코드 별칭
별칭 의미
.enter Enter(엔터) 키를 눌렀을 때
.tab Tab(탭) 키를 눌렀을 때
.delete Delete(딜리트) 키를 눌렀을 때
.esc ESC 키를 눌렀을 때
.space Space(스페이스) 키를 눌렀을 때
.up 화살표 위 키를 눌렀을 때
.down 화살표 아래 키를 눌렀을 때
.left 화살표 왼쪽 키를 눌렀을 때
.right 화살표 오른쪽 키를 눌렀을 때
시스템 장식자
별칭 의미
.ctrl Ctrl(컨트롤) 키가 눌린 경우
.alt Alt(안트) 키가 눌린 경우
.shift Shift(시프트) 키가 눌린 경우
.meta Meta(메타) 키가 눌린 경우
v-model 장식자
장식자 의미
.lazy input 대신 change 이벤트 핸들링
.number 값을 숫자로 변환
.trim 값 양쪽에 있는 쓸데없는 공백 제거

데이터 가공 및 감시

new Vue({
  // ..
  watch: {
    <감시할 데이터>: function(<새로운 값>, <이전 값>) {
      // value가 변화했을 때 하고 싶은 처리
    },
    'item.value': function(newVal, oldVal) {
      // 객체의 속성도 감시할 수 있음
    },
    list: {
      handler: function(newVal, oldVal) {
        // list가 변경될 때 하고 싶은 처리
      },
      deep: true,  // 속성: deep, 값: Boolean, 네스트된 객체도 감시할지
      immediate: true  // 속성: immediate, 값: Boolean, 처음 값을 읽어 들이는 시점에도 호출할지
    }
  }
})

사용자 정의 디렉티브에서 사용할 수 있는 훅
메서드 이름 시점
bind 디렉티브가 처음 요소와 연결될 때
inserted 연결된 요소가 부모 Node에 삽입될 때
update 연결된 요소를 내포하고 있는 컴포넌트의 VNode가 변경되었을 때
componetUpdated 내포하고 있는 컴포넌트와 자식 컴포넌트의 VNode가 변경되었을 때
unbind 연결되어 있는 요소로부터 디렉티브가 제거될 때
훅 매개변수
매개변수 내용
el 디렉티브가 연결되어 있는 요소
binding 배인드된 값, 매개변수, 장식자가 들어 있는 객체
vnode 요소에 대응되는 VNode
oldVnode 변경 이전의 VNode(update 또는 componentUpdated에서만 사용 가능)
binding의 속성
속성 설명
arg 매개변수
modifiers 장식자 객체
value 새로운 값
oldValue 이전 값(update 또는 componentUpdated에서만 사용 가능)

Components

Transition & Animation

트랜지션 클래스의 시점
Enter 계열의 클래스 대상 요소가 DOM에서 삽입될 때의 트랜지션 페이즈
.v-enter 대상 요소가 DOM에 삽입되기 전에 추가되며, 트랜지션이 종료될 때 사라짐. Enter 액티브 상태
.v-enter-to 트랜지션이 실제로 시작될 때 추가되며, 트랜지션이 종료될 때 사라짐. Enter의 종료 완료
.v-enter-active 대상 요소가 DOM에 삽입되기 전에 추가되며, 트랜지션이 종료될 때 사라짐. Enter의 액티브 상태
Leave 계열의 클래스 대상 요소가 DOM에서 제거될 때의 트랜지션 페이즈
.v-leave 트랜지션 시작 전에 추가되며, 트랜지션 개시 때는 사라짐. Leave 시작 상태
.v-leave-to 트랜지션 시작 전에 추가되어, 트랜지션이 종료되었을 때 사라짐. Leave 종료 상태
.v-leave-active 트랜지션 시작 전에 추가되어, 트랜지션이 종료되었을 때 사라짐. Leave의 액티브 상태
Enter와 Leave 시점 변경
모드 동작
in-out Enter 트랜지션이 종료되고 나서 Leave 트랜지션 시작
out-in Leave 트랜지션이 종료되고 나서 Enter 트랜지션 시작
사용할 수 있는 트랜지션 훅
Enter 계열 훅 시점
before-enter DOM에 요소가 추가되기 전
enter .v-enter가 있는 DOM에 요소가 추가된 후
after-enter 트랜지션이 끝나거나 또는 enter에서 done()을 호출한 후
enter-cancelled enter 페이즈가 중간에 취소되었을 때
Leave 계열 훅 시점
before-leave 클래스가 추가되기 전
leave .v-leave가 추가된 후
after-leave DOM에서 요소가 제거된 후 또는 leave에서 done()을 호출한 후
leave-cancelled leave 페이즈가 중간에 취소되었을 때

Applications

Node.js

npm 기본 명령어
명령어 생략 기법 설명
npm install –global npm i -g 전역 위치에 설치
npm install –save npm i -s 프로젝트 결과물을 동작시키기 위해서 필요한 패키지를 설치
npm install –save-dev npm i -D 개발 중에만 필요한 패키지 설치

Vue CLI

$ npm install -g vue-cli  # vue-cli 설치

$ vue --version  # 버전 확인

# 프로젝트 생성 명령어의 기본 형태
$ vue init <템플릿 이름> <프로젝트 이름>
$ cd <프로젝트 이름>
$ npm install

$ vue init webpack my-app

$ npm run dev  # 개발 서버 실행

$ npm run build  # 프로젝트 빌드

Vue.js 플러그인

// Vue와 Vuex 모듈 읽어 들이기
import Vue from 'vue'
import Vuex from 'vuex'

// Vue에 Vuex 등록하기
Vue.use(Vuex)

Vuex

# 최신 버전 설치
$ npm install vuex babel-polyfill

# 버전 지정
$ npm install vuex@3.1.0 babel-polyfill@6.26.

import 'babel-polyfill'
import Vue from 'vue'
import Vuex from 'vuex'

// 플러그인으로 등록
Vue.use(Vuex)

// 스토어 만들기
const store = new Vuex.store({
  state: {
    count: 0
  },
  mutations: {
    // 카운트 업하는 뮤테이션 등록, 매개변수로 전달
    increment(state) {
      state.count++
    }
    // increment: state => { state.count++ }  // 위와 같은 동작을 하는 코드 
  }
})

export default store

import store from '@/store.js'  // @는 디폴트로 등록되어 있는 src 디렉토리의 별칭
console.log(store.state.count)  // -> 0

// 스토어의 상태 변경
// increment 커밋
store.commit('increment')
// 값이 변경된 것을 확인
console.log(store.state.count)  // -> 1

import store from './store.js'

new Vue({
  el: '#app',
  store,  // store 등록
  render: h => h(App)
})

export default {
  created() {
    // 스토어의 상태 확인
    console.log(this.$store.state.count)
    // 스토어의 상태 변경
    this.$store.commit('increment')
  }
}

Vue Router로 SPA 만들기

Vue Router 설치

$ npm install vue-router  # 최신 버전 설치

$ npm install vue-router@3.0.6  # 버전 지정

import Vue from 'vue'
import VueRouter from 'vue-router'

// 플러그인으로 등록
Vue.use(VueRouter)

Vue Router 내장 컴포넌트
사용자 정의 태그 설명
<router-view> 라우트와 일치하는 컴포넌트를 렌더링
<router-link> 라우트 링크를 생성
import Vue from 'vue'
import VueRouter from 'vue-router'

// 라우트 전용 컴포넌트 읽어 들이기
import Home from '@/views/Home.vue'
import Product from '@/views/Product.vue'

// Vuex와 마찬가지로 플러그인 등록
Vue.use(VueRouter)

// VueRouter 인스턴스 생성
const router = new VueRouter({
  // URL의 경로와 연결할 컴포넌트 맵핑하기
  routes: [
    { path: '/', component: Home },
    { path: '/product', component: Product }
  ]
})

// 생성한 VueRouter 인스턴스 익스포트
export default router
import router from './router.js'

new Vue({
  el: '#app',
  router,  // 애플리케이션 등록
  render: h => h(App)
})

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link>
      <router-link to="/product">상품 정보</router-link>
    </nav>
    <!-- 여기에 경로에 일치하는 컴포넌트가 들어감 -->
    <router-view />
  </div>
</template>

객체 형식으로 지정
객체 설명
name 라우트 이름
path 라우트 경로
params 요청 매개변수 객체
query 쿼리 객체
액티브 링크 하이라이트
클래스 설명
.router-link-exact-active 전체가 매치되는 라우트
.router-link-active 매치한 경로를 포함하는 라우트
프로그램으로 내비게이션
메서드 설명
push 이력 엔트리 추가
replace 이력 엔트리 수정
go 브라우저 레벨에서 페이지 이동
내비게이션 가드의 매개변수
매개 변수 설명
to 이동 후의 라우트 객체
from 이동 전의 라우트 객체
next 내비게이션 해결 전용 콜백 함수
라우트 단위 가드
메서드 이름 시점
beforeEnter 라우트 이동 전
전역 가드
메서드 이름 시점
beforeEach 모든 라우트의 이동 전, 컴포넌트 가드 해결 전
beforeResolve 모든 라우트의 이동 전, 컴포넌트 가드 해결 후
afterEach 모든 라우트의 이동 후
컴포넌트 가드
메서드 이름 시점
beforeRoutEnter 해당 컴포넌트로 이동하기 전
beforeRouteUpdate 해당 컴포넌트에서 라우트가 변경되기 전
beforeRouteLeave 해당 컴포넌트에서 밖으로 이동하기 전

컴포넌트 데이터 전달

Props 속성을 이용한 Parent to Child 컴포넌트 데이터 전달

Parent는 v-bind, Child는 props를 이용
<template>
  <div> 하위 컴포넌트에 데이터 값을 알려줍니다. 
    <ChildComponent v-bind:childVaule="parentVaule" /> 
  </div> 
</template> 

<script> 
import ChildComponent from "@/components/childComponent.vue"; 

export default { 
  name: "ParentComponent", 
  components: { ChildComponent }, 
  data: function () { 
    return { 
      parentVaule: 20, 
    }; 
  }, 
}; 
</script>
<template>
  <div>{{ this.childVaule }} : 상위 컴포넌트로부터 받아온 값</div>
</template>

<script> 
export default { 
  name: "ChildComponent", 
  props: ["childVaule"], }; 
</script>

Child to Parent 컴포넌트 데이터 전달

Child에서 $emit, Parent에서 v-on을 이용
<template>
  <button @click="updateParentValue">클릭시 부모의 데이터 값이 증가합니다.</button> 
</template> 

<script> 
export default { 
  name: "ChildComponent", 
  methods: { 
    updateParentValue() { 
      this.$emit("childEvent"); 
    }, 
  },
}; 
</script>
<template> 
  <div> 
    <ChildComponent v-on:childEvent="updateParentValue" /> 
  </div> 
</template> 

<script> 
import ChildComponent from "@/components/childComponent.vue"; 

export default { 
  name: "ParentComponent", 
  components: { ChildComponent }, 
  data: function () { 
    return { 
      parentVaule: 20, 
    }; 
  }, 
  methods: { 
    updateParentValue() { 
      this.parentVaule++; 
      console.log(this.parentVaule) // 21, 22, 22, 누를때마다 증가하는 것 확인 가능 
    }, 
  }, 
}; 
</script>

기타(Sibling, 손자) 컴포넌트 데이터 전달

EventBus를 이용, Vuex 이용.

References

1)
kebab-case, lisp-case, spinal-case; 하이픈으로 구분