Vue


자바스크립트 웹 어플리케이션 프레임워크

프로젝트 생성 및 개발환경 실행

npm install -g @vue/cli
vue create {프로젝트 이름}
cd {프로젝트 이름}
npm run serve

컴포넌트 import

  • Vue 컴포넌트는 다음과 같은 형태로 구성되어 있으며, 다음처럼 import 할 수 있다.
  • <template>
    <MainHeader />
    </template>
    <script>
    import MainHeader from './components/layout/MainHeader.vue';
    export default {
    name: 'App',
    components: {
    MainHeader,
    },
    };
    </script>
    <style>
    #app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
    }
    </style>

    Router 사용

    npm install vue-router

    main.js

    import { createApp } from 'vue';
    import App from './App.vue';
    import router from './router';
    const app = createApp(App);
    app.use(router);
    app.mount('#app');

    router.js

    import { createRouter, createWebHistory } from 'vue-router';
    import MainHome from './views/MainHome.vue';
    import MainAbout from './views/MainAbout.vue';
    import MainCounter from './views/MainCounter.vue';
    const routes = [
    {
    path: '/',
    component: MainHome,
    },
    {
    path: '/about',
    component: MainAbout,
    },
    { path: '/count', component: MainCounter },
    ];
    const router = createRouter({
    history: createWebHistory(),
    routes,
    });
    export default router;

    App.vue

  • router-view를 이용하면 해당 위치에 현재 URL에서 routing 되는 컴포넌트를 넣어줄 수 있다.
  • <template>
    <MainHeader />
    <div id="content" class="content">
    <router-view></router-view>
    </div>
    </template>

    MainHeader.vue

  • router-link를 이용해 다른 URL로 보내줄 수 있다.
  • <ul>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    </ul>

    Data Binding

  • data() {} 안에 return으로 사용할 data들을 넣어준다.
  • methods : {} 안에 메소드들을 선언할 수 있다.
  • {{}}안에 data명을 입력하면 표시된다.
  • input태그의 DOM 컨트롤을 할 때에는 v-model로 해당 data명을 적어준다.
  • @click 속성으로 onClick 메소드를 넣어줄 수 있다.
  • <template lang="">
    <div>
    <h1>Welcome to {{ title }}!</h1>
    <input type="text" v-model="inputValue" />
    <button @click="getData">Get</button>
    <button @click="setData">Set</button>
    </div>
    </template>
    <script>
    export default {
    data() {
    return {
    title: 'HOME',
    inputValue: 'Hi',
    };
    },
    methods: {
    getData() {
    alert(this.inputValue);
    },
    setData() {
    this.inputValue = 'Changed';
    },
    },
    }
    </script>

    Watch

  • watch를 이용하면 data가 변경될 때마다 특정 코드를 실행할 수 있다.
  • watch: {
    inputValue() {
    console.log('watch', this.inputValue);
    },
    },

    생명주기 메소드

  • 생명주기 메소드를 이용해 리액트의 useEffect 훅과 같은 기능을 구현할 수 있다.
  • 아래는 공식문서의 생명주기 표이다.
  • beforeMount() {
    console.log('beforeMount');
    },
    mounted() {
    console.log('mounted');
    },
    beforeUpdate() {
    console.log('beforeUpdate');
    },
    updated() {
    console.log('updated');
    console.log('inputValue', this.inputValue);
    },
  • 위와 같이 사용할 수 있다.
  • v-for (반복 렌더링)

  • 리액트의 .map() 메소드를 사용할 수 있다.
  • <template lang="">
    <div>
    <div :key="el" v-for="el in divArr">{{ el }}</div>
    </div>
    </template>
    <script>
    export default {
    data() {
    return {
    divArr: ['1', '2', '3', '4', '5'],
    };
    },
    }
    </script>
  • :key 를 이용해 key를 넣어주고, v-for=”el in Arr”로 반복해준다.
  • v-if, v-show (조건부 렌더링)

  • v-if를 사용할 때는 v-elsev-else-if 도 사용할 수 있다.
  • v-show 는 사용법이 v-if와 동일하나 v-else 와 상호작용하지 않는다.
  • <div v-if="isDivShowed">Div1</div>
    <div v-show="isDivShowed">Div2</div>
    u default {
    data() {
    return {
    isDivShowed: false,
    }
    },
    }
  • v-if vs v-show
  • Vuex

    Vue의 전역 상태 관리 라이브러리

    설치

    npm install vuex --save

    Store 생성

  • /src/store/index.js
  • import Vuex from 'vuex'
    const store = new Vuex.Store({
    state: {
    count: 0
    },
    mutations: {
    increment: state => state.count++,
    decrement: state => state.count--
    }
    })
    export default store

    컴포넌트에서 사용

  • /src/views/MainCounter.vue
  • <template lang="">
    <div>
    <h1>Counter</h1>
    <div>{{ count }}</div>
    <button @click="up">UP</button>
    <button @click="down">DOWN</button>
    </div>
    </template>
    <script>
    import store from '../store/index'
    export default {
    computed: {
    count() {
    return store.state.count
    }
    },
    methods: {
    up() {
    store.commit('increment')
    },
    down() {
    store.commit('decrement')
    }
    }
    }
    </script>
    <style lang=""></style>
  • computed를 이용해 store에 있는 값을 가져와서 사용한다.
  • .commit() 을 이용해 mutation을 가져와서 사용한다.
  • payload 전달

    import Vuex from 'vuex'
    const store = new Vuex.Store({
    state: {
    count: 0
    },
    mutations: {
    increment: (state, payload) => {
    state.count += payload.amount
    },
    decrement: (state, payload) => {
    state.count -= payload.amount
    }
    }
    })
    export default store
    <template lang="">
    <div>
    <h1>Counter</h1>
    <div>{{ count }}</div>
    <button @click="up">UP</button>
    <button @click="down">DOWN</button>
    </div>
    </template>
    <script>
    import store from '../store/index'
    export default {
    computed: {
    count() {
    return store.state.count
    }
    },
    methods: {
    up() {
    store.commit('increment', { amount: 10 })
    },
    down() {
    store.commit('decrement', { amount: 10 })
    }
    }
    }
    </script>
    <style lang=""></style>
  • 이렇게 하면 amount에 등록된 값이 전달되어 10씩 증가하고, 10씩 감소한다.
  • payload는 꼭 객체로 사용하지 않아도 된다.
  • getters 사용

  • /src/store/index.js
  • import Vuex from 'vuex'
    const store = new Vuex.Store({
    state: {
    count: 0,
    todos: [
    { id: 1, text: '1번', done: true },
    { id: 2, text: '2번', done: false },
    { id: 3, text: '3번', done: true },
    { id: 4, text: '4번', done: false },
    { id: 5, text: '5번', done: true },
    { id: 6, text: '6번', done: false }
    ]
    },
    getters: {
    doneTodo: state => state.todos.filter(el => el.done === true),
    haveTodo: state => state.todos.filter(el => el.done === false)
    },
    mutations: {
    increment: (state, payload) => {
    state.count += payload.amount
    },
    decrement: (state, payload) => {
    state.count -= payload.amount
    }
    }
    })
    export default store
  • 이렇게 하면 이미 filter가 적용되어 있는 todo만 가져올 수 있다.
  • /src/views/GetTodo.vue
  • <template lang="">
    <div>
    <div>DoneTodo</div>
    <div :key="el.id" v-for="el in doneTodo">{{ el.text }}</div>
    <br />
    <div>HaveTodo</div>
    <div :key="el.id" v-for="el in haveTodo">{{ el.text }}</div>
    </div>
    </template>
    <script>
    import store from '@/store'
    export default {
    computed: {
    doneTodo() {
    return store.getters.doneTodo
    },
    haveTodo() {
    return store.getters.haveTodo
    }
    }
    }
    </script>
    <style lang=""></style>
  • 컴포넌트에서는 위처럼 사용한다.