Lined Notebook

Vue.js 개념정리

by yjym33

1. 데이터 바인딩

 

데이터 바인딩(Data Binding)이란 무엇인가요?

 

  • *데이터 바인딩(Data Binding)**은 사용자 인터페이스(UI) 요소와 데이터 모델 간의 동기화를 의미합니다. 즉, 데이터 바인딩은 UI 요소에 데이터를 표시하고 사용자 입력을 데이터 모델에 반영하는 프로세스를 자동화하는 기술입니다. Vue.js에서는 데이터 바인딩이 매우 쉽고 강력하게 구현되어 있으며, 개발자가 UI와 데이터 간의 관계를 간단하게 관리할 수 있게 해줍니다.

 

Vue.js의 주요 데이터 바인딩 유형:

 

1. 단방향 데이터 바인딩(One-Way Data Binding):

  • 데이터의 변경이 UI에 반영되는 방향으로만 동작합니다.
  • Vue.js에서는 {{ }} 또는 v-bind 디렉티브를 사용하여 구현할 수 있습니다.
  • 예: <p>{{ message }}</p>

 

2. 이벤트 바인딩(Event Binding):

  • 사용자의 동작(예: 클릭)을 특정 메서드나 함수에 연결하여 실행하는 바인딩 방식입니다.
  • Vue.js에서는 v-on 디렉티브를 사용하여 구현할 수 있습니다.
  • 예: <button v-on:click="doSomething">Click me</button>
  1. 양방향 데이터 바인딩(Two-Way Data Binding):
    • 데이터의 변경이 UI에 반영되는 방향과 UI 요소에서의 변경이 데이터에도 반영되는 양방향 동작을 의미합니다.
    • Vue.js에서는 v-model 디렉티브를 사용하여 구현할 수 있습니다.
    • 예: <input v-model="message">

데이터 바인딩을 하는 이유?

  1. HTML로 하드코딩을 해놓으면 나중에 변경하기가 어렵기 때문에
  2. Vue의 실시간 자동 렌더링 기능을 사용하기 위해서
    1. Vue는 data 부분에서 data를 변경하면 자동으로 HTML 부분에 이부분들을 반영한다.
    2. 자주 변할것 같은 데이터들은 데이터에 저장후 데이터 바인딩으로 작업하는것이 좋음

 

2. 디렉티브

디렉티브란 무엇인가요?

  • *디렉티브(Directives)**는 Vue.js에서 제공하는 특별한 속성으로, HTML 요소에 추가하여 요소의 동작 및 모양을 제어하는 역할을 합니다. 디렉티브는 v- 접두사로 시작하며, Vue 인스턴스의 데이터와 연결하여 동적으로 DOM을 조작하는 데 사용됩니다.

 

주요 Vue.js 디렉티브:

 

  1. v-bind 디렉티브:
    • 요소의 속성(Attribute) 값을 동적으로 설정할 때 사용됩니다.
    • 예: <img v-bind:src="imageSrc"> (이미지의 src 속성을 imageSrc 데이터에 바인딩)
  2. v-model 디렉티브:
    • 양방향 데이터 바인딩을 제공하며, 폼 요소의 값을 Vue 데이터와 동기화할 때 사용됩니다.
    • 예: <input v-model="message"> (입력 필드의 값을 message 데이터와 양방향 바인딩)
  3. v-for 디렉티브:
    • 리스트나 배열을 순회하며 반복 요소를 렌더링할 때 사용됩니다.
    • 예: <li v-for="item in items">{{ item }}</li> (리스트 **items**의 각 항목을 반복하여 리스트 아이템 생성)
    • <태그 v-for=”작명 in 몇회 key : 작명”> 이런 방식으로 동작함 (key는 반드시 넣어야함)
  4. v-if, v-else-if, v-else 디렉티브:
    • 조건부 렌더링을 제공하며, 조건에 따라 요소를 표시하거나 감출 때 사용됩니다.
    • 예: <p v-if="isVisible">이 내용은 표시됩니다.</p>
  5. v-show 디렉티브:
    • 요소를 조건에 따라 숨기거나 보일 때 사용됩니다. **v-if**와 다르게 요소는 항상 렌더링되며 CSS로 숨깁니다.
    • 예: <div v-show="isVisible">이 내용은 보입니다.</div>
  6. v-on 디렉티브:
    • 이벤트 처리를 위해 사용되며, 요소에 이벤트 리스너를 추가할 때 사용됩니다.
    • 예: <button v-on:click="doSomething">클릭</button> (버튼 클릭 시 doSomething 메서드 호출)

 

사용자 정의 디렉티브:

 

Vue.js에서는 사용자 정의 디렉티브를 생성하여 커스텀 동작을 추가할 수도 있습니다. 이러한 커스텀 디렉티브는 bind, inserted, update, componentUpdated, **unbind**와 같은 라이프사이클 후크를 활용하여 정의됩니다.

 

3. 이벤트 처리

 

1. 이벤트 바인딩 (Event Binding): Vue.js에서 이벤트 처리는 v-on 디렉티브를 사용하여 DOM 요소에 이벤트를 연결합니다. 이벤트 바인딩은 다음과 같이 작성됩니다

<button v-on:click="doSomething">클릭하세요</button>

 

2.이벤트 핸들러 (Event Handlers): 이벤트 바인딩은 템플릿 내부에서 메서드를 호출하는 방법으로, 이 메서드는 이벤트 핸들러 역할을 합니다.

methods: {
  doSomething() {
    // 이벤트 핸들러 로직
  }
}

 

3. 이벤트 객체 (Event Object): 이벤트 핸들러 메서드에는 종종 이벤트 객체가 전달됩니다. 이 객체에는 이벤트와 관련된 정보가 포함되어 있으며, 이를 활용하여 이벤트 처리 로직을 작성할 수 있습니다.

methods: {
  handleClick(event) {
    console.log(event.target); // 클릭된 요소
  }
}

 

4.이벤트 수식어 (Event Modifiers): Vue.js는 이벤트 처리를 더 세밀하게 제어하기 위한 이벤트 수식어를 제공합니다. 예를 들어, .stop, .prevent, .once, .self 등의 수식어를 사용하여 이벤트 동작을 변경할 수 있습니다.

<a v-on:click.stop="doSomething">링크</a>

 

5. 메서드를 이용한 이벤트 처리: 이벤트 핸들러 메서드 외에도 인라인 JavaScript 표현식을 사용하여 이벤트 처리를 할 수 있습니다. 이를 통해 간단한 로직을 직접 템플릿에 작성할 수 있습니다.

 

<button v-on:click="counter++">{{ counter }}</button>

 

4. 조건부 렌더링

 

1. v-if 디렉티브: v-if 디렉티브는 지정된 조건이 **true**일 때만 요소를 렌더링합니다. 조건이 **false**이면 요소는 DOM에서 제거됩니다.

<p v-if="isShown">이것은 보여질 때만 표시됩니다.</p>

 

2. v-else와 v-else-if 디렉티브: **v-else**와 v-else-if 디렉티브를 사용하여 **v-if**와 함께 조건부 렌더링을 확장할 수 있습니다.

<div v-if="status === 'success'">성공 메시지</div>
<div v-else-if="status === 'error'">에러 메시지</div>
<div v-else>기본 메시지</div>

 

3. v-show 디렉티브: v-show 디렉티브는 조건이 **true**이면 요소를 화면에 표시하고, 조건이 **false**이면 CSS **display: none**을 적용하여 요소를 숨깁니다. 이것은 요소를 DOM에서 완전히 제거하지 않고 숨기는 방법입니다.

<p v-show="isShown">이것은 화면에 항상 존재하지만, CSS로 숨깁니다.</p>

 

4. <template> 요소를 활용한 조건부 렌더링: <template> 요소를 사용하여 여러 요소를 그룹화하고 조건에 따라 그룹 전체를 렌더링할 수 있습니다.

<template v-if="isShown">
  <p>첫 번째 문장</p>
  <p>두 번째 문장</p>
</template>

 

5. 계산된 속성 (Computed Properties): 조건부 렌더링 로직을 더 복잡하게 만들 때, 계산된 속성을 활용하여 템플릿에서 더 깔끔한 조건부 렌더링을 구현할 수 있습니다.

computed: {
  shouldShowMessage() {
    return this.status === 'success';
  }
}
<div v-if="shouldShowMessage">성공 메시지</div>

 

5. 리스트 렌더링

 

1. v-for 디렉티브: v-for 디렉티브를 사용하여 배열이나 객체를 순회하고 각 요소를 템플릿에 렌더링합니다. 이 디렉티브는 item in items 형식으로 사용되며 **item**은 개별 요소를 나타냅니다.

<ul>
  <li v-for="item in items">{{ item }}</li>
</ul>

 

2. 인덱스 접근: v-for 디렉티브를 사용할 때 두 번째 매개변수로 인덱스에 접근할 수 있습니다.

<ul>
  <li v-for="(item, index) in items">{{ index + 1 }}. {{ item }}</li>
</ul>

 

3. v-for로 객체 순회: 객체를 순회할 때 **v-for**를 사용할 수 있으며, 이 때는 키-값 쌍을 얻습니다.

<ul>
  <li v-for="(value, key) in object">{{ key }}: {{ value }}</li>
</ul>

 

4.범위 순회: 숫자 범위를 생성하여 **v-for**를 사용하여 반복할 수 있습니다.

<ul>
  <li v-for="n in 5">{{ n }}</li>
</ul>

 

5. key 속성: **v-for**를 사용할 때 각 요소에 고유한 key 속성을 지정하여 Vue.js가 더 효율적으로 DOM 업데이트를 수행하도록 도와줍니다.

<ul>
  <li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>

 

6. v-for와 컴포넌트: v-for 디렉티브를 사용하여 컴포넌트를 반복적으로 렌더링할 수 있습니다. 이것은 재사용 가능한 컴포넌트를 만들고 동적 목록을 생성할 때 유용합니다.

<custom-component v-for="item in items" :key="item.id" :data="item"></custom-component>

 

7. 계산된 속성과 필터: 리스트 렌더링과 관련된 로직을 보다 복잡하게 만들 때, 계산된 속성이나 필터를 활용하여 템플릿 코드를 깔끔하게 유지할 수 있습니다.

computed: {
  filteredItems() {
    return this.items.filter(item => item.type === 'fruit');
  }
}
<ul>
  <li v-for="item in filteredItems">{{ item.name }}</li>
</ul>

 

6. 컴포넌트

 

1. 컴포넌트 정의:

 

컴포넌트는 Vue.component 메서드를 사용하여 정의됩니다. 간단한 컴포넌트를 정의하는 예제를 살펴보겠습니다

Vue.component('my-component', {
  // 컴포넌트 옵션들
});

 

2. 컴포넌트 템플릿:

 

각 컴포넌트는 템플릿을 가질 수 있으며, 템플릿은 해당 컴포넌트의 렌더링 방식을 정의합니다. 템플릿은 HTML 또는 Vue.js의 템플릿 언어를 사용하여 작성됩니다.

Vue.component('my-component', {
  template: '<div>이것은 컴포넌트입니다.</div>'
});

 

 

3. 컴포넌트 데이터:

 

컴포넌트는 자체 데이터를 가질 수 있으며, 데이터는 함수로 정의되어야 합니다. 각 인스턴스는 데이터의 복사본을 가지게 되므로 컴포넌트 간에 상태가 격리됩니다.

Vue.component('my-component', {
  data: function() {
    return {
      message: '안녕하세요!'
    };
  }
});

 

4. 컴포넌트 사용:

<my-component></my-component>

 

 

5. 컴포넌트 인스턴스:

 

컴포넌트는 Vue 인스턴스와 유사하게 인스턴스화됩니다. 컴포넌트를 사용하면 여러 인스턴스를 생성하여 독립된 컴포넌트를 만들 수 있습니다.

var vm = new Vue({
  el: '#app',
  data: {
    // 애플리케이션 데이터
  }
});

var myComponentInstance = new Vue({
  el: '#component',
  data: {
    // 컴포넌트 데이터
  }
});

 

7. 라이프사이클 훅 (Lifecycle Hooks):

Vue.js에서 컴포넌트 라이프사이클 훅(Component Lifecycle Hooks)은 컴포넌트가 생성, 업데이트, 파괴되는 일련의 단계에서 실행되는 함수 또는 메서드입니다.

이 훅들은 컴포넌트의 상태 변화와 동작을 감시하고 제어하는 데 사용됩니다.

 

  1. beforeCreate: 컴포넌트가 생성되고 초기화되기 전에 실행됩니다. 이 시점에서는 데이터나 이벤트 등이 초기화되지 않았습니다.
  2. created: 컴포넌트가 생성되고 데이터가 초기화된 직후에 실행됩니다. 이 시점에서 데이터와 이벤트에 접근할 수 있습니다. API 호출과 초기화 로직을 주로 수행합니다.
  3. beforeMount: 컴포넌트가 DOM에 마운트되기 직전에 실행됩니다. 템플릿이 컴파일되었지만 실제 DOM에는 아직 적용되지 않았습니다.
  4. mounted: 컴포넌트가 DOM에 성공적으로 마운트된 직후에 실행됩니다. 이 시점에서 실제 DOM에 접근할 수 있으므로 외부 라이브러리 초기화나 비동기 작업을 수행하는 데 유용합니다.
  5. beforeUpdate: 컴포넌트의 데이터가 변경되어 업데이트되기 직전에 실행됩니다. 이 시점에서 변경 전 데이터에 접근할 수 있습니다.
  6. updated: 컴포넌트의 데이터가 변경되어 업데이트된 직후에 실행됩니다. 이 시점에서 변경된 데이터로 업데이트된 DOM이 렌더링됩니다.
  7. beforeDestroy: 컴포넌트가 파괴되기 직전에 실행됩니다. 이 시점에서 컴포넌트의 정리 작업, 이벤트 리스너 해제, 타이머 제거 등을 수행할 수 있습니다.
  8. destroyed: 컴포넌트가 파괴된 직후에 실행됩니다. 이 시점에서 컴포넌트의 모든 이벤트 리스너와 뷰 인스턴스가 제거되며 메모리에서 해제됩니다.
  9. activated (2.3.0 이상): keep-alive 컴포넌트가 활성화될 때 실행됩니다. (예: 탭 간 전환)
  10. deactivated (2.3.0 이상): keep-alive 컴포넌트가 비활성화될 때 실행됩니다. (예: 탭 간 전환)
  11. errorCaptured (2.5.0 이상): 하위 컴포넌트에서 발생한 에러를 잡아내는 데 사용됩니다. 부모 컴포넌트에서 이 훅을 정의하면 하위 컴포넌트에서 발생한 에러를 처리하거나 로깅할 수 있습니다.

 

8. 컴퓨티드 속성 (Computed Properties):

컴퓨티드 속성(Computed Properties)은 데이터 속성을 기반으로 계산된 값을 제공하는 속성입니다. 컴퓨티드 속성은 데이터의 변화를 감지하고 자동으로 다시 계산되며, 이를 통해 간단한 계산부터 복잡한 데이터 가공 및 필터링 작업을 수행할 수 있습니다. 컴퓨티드 속성을 사용하면 템플릿에서 함수를 직접 호출하는 대신 데이터를 더 쉽게 표현할 수 있으며, 가독성을 높일 수 있습니다.

 

1. 기본 구문

computed: {
  // 컴퓨티드 속성 이름
  computedPropertyName: function() {
    // 계산 로직
    return computedValue;
  }
}

컴퓨티드 속성은 computed 객체 안에 정의됩니다. 각 컴퓨티드 속성은 이름과 계산 함수로 구성되며, 함수는 해당 컴퓨티드 속성의 값을 계산하고 반환합니다.

  • computedPropertyName: 컴퓨티드 속성의 이름을 정의합니다.
  • function() { /* 계산 로직 */ }: 컴퓨티드 속성의 값을 계산하는 함수를 정의합니다.
  • return computedValue;: 계산된 값을 반환합니다.

 

2. 캐싱(Caching):

 

컴퓨티드 속성은 캐싱되어 성능을 향상시킵니다. 즉, 의존하는 데이터 속성의 값이 변경되지 않는 한 컴퓨티드 속성의 계산은 한 번만 이루어집니다. 이는 계산 비용이 높은 작업을 효율적으로 처리할 수 있도록 도와줍니다.

 

3. 종속성(Dependency) 정의:

 

컴퓨티드 속성 내에서 사용하는 데이터 속성을 종속성으로 정의해야 합니다. Vue.js는 종속성을 추적하고 해당 데이터가 변경될 때만 컴퓨티드 속성을 재계산합니다.

computed: {
  fullName: function() {
    // firstName과 lastName을 종속성으로 정의
    return this.firstName + ' ' + this.lastName;
  }
}

 

 

4. 접근 방식:

 

컴퓨티드 속성은 템플릿에서 데이터 속성처럼 접근할 수 있습니다. 템플릿에서는 속성을 읽는 것처럼 사용할 수 있으며, Vue.js는 내부적으로 컴퓨티드 속성의 값을 필요할 때마다 자동으로 계산합니다.

<p>{{ fullName }}</p>

 

 

5. Setter 함수:

 

컴퓨티드 속성은 기본적으로 읽기 전용이지만 필요한 경우 해당 속성의 값을 설정할 수 있는 setter 함수를 정의할 수 있습니다. 이를 통해 컴퓨티드 속성을 업데이트할 수 있습니다.

computed: {
  fullName: {
    get: function() {
      return this.firstName + ' ' + this.lastName;
    },
    set: function(newValue) {
      // setter 함수로 컴퓨티드 속성 업데이트 로직 정의
    }
  }
}

 

9. 상태관리 (Vuex)

 

  1. 상태(State):Vuex의 핵심은 애플리케이션의 상태를 중앙 집중식으로 관리하는 것입니다. 상태는 애플리케이션 내의 모든 컴포넌트에서 공유되는 데이터를 나타냅니다. 이 상태는 일반적으로 객체 형태로 정의되며 애플리케이션의 전반적인 데이터 구조를 포함합니다.
  2. 뮤테이션(Mutations):뮤테이션은 Vuex 상태를 변경하기 위한 유일한 방법입니다. 뮤테이션은 상태를 변경하는 순수한 함수로, 이전 상태와 커밋된 상태를 받아 새로운 상태로 변경합니다. 뮤테이션은 상태 변화를 추적하고 디버깅할 때 매우 유용합니다.
  3. 액션(Actions):액션은 비동기 작업을 수행하거나 여러 뮤테이션을 연달아 호출하는 역할을 합니다. 일반적으로 사용자 입력, API 호출 등과 같은 비동기 작업을 처리할 때 액션을 사용합니다. 액션은 컴포넌트에서 호출되고 뮤테이션을 커밋하여 상태를 변경합니다.
  4. 게터(Getters):게터는 Vuex 상태를 계산된 속성으로 제공하는 역할을 합니다. 상태를 가공하거나 필터링하여 컴포넌트에서 사용할 때 유용합니다. 게터는 일반적인 데이터 속성처럼 접근하며, 캐싱을 통해 성능을 최적화합니다.
  5. 모듈(Modules):Vuex에서는 모듈을 사용하여 상태, 뮤테이션, 액션, 게터를 모듈화할 수 있습니다. 이를 통해 애플리케이션 상태를 여러 모듈로 분할하고 유지 관리할 수 있습니다. 모듈은 네임스페이스를 가지고 있어 중복된 모듈명을 허용하지 않습니다.
  6. 중앙 집중식 상태 관리:Vuex는 중앙 집중식 상태 저장소를 통해 상태를 관리하므로 상태가 컴포넌트 간에 공유됩니다. 이를 통해 데이터 흐름을 추적하고 예측 가능한 방식으로 상태를 변경할 수 있습니다.
  7. 단방향 데이터 흐름:Vuex는 상태를 변경하는 유일한 방법인 뮤테이션을 통해 데이터 흐름을 단방향으로 유지합니다. 이로써 상태의 변화가 예측 가능하며 디버깅이 용이합니다.

 

8. Vuex 모듈 생성

// src/store/modules/todo.js

// 상태
const state = {
  todos: []
};

// 뮤테이션
const mutations = {
  ADD_TODO: (state, newTodo) => {
    state.todos.push(newTodo);
  }
};

// 액션
const actions = {
  addTodo: ({ commit }, newTodo) => {
    commit('ADD_TODO', newTodo);
  }
};

// 게터
const getters = {
  getTodos: (state) => state.todos
};

export default {
  state,
  mutations,
  actions,
  getters
};

 

모듈 등록

 

// src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
import todoModule from './modules/todo';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    todoModule
  }
});

 

컴포넌트에서 Vuex 사용

 

<!-- src/components/TodoList.vue -->

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo" placeholder="새 할 일 추가">
    <ul>
      <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
    </ul>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState('todoModule', ['todos']),
    newTodo: {
      get() {
        return this.$store.state.todoModule.newTodo;
      },
      set(value) {
        this.$store.commit('todoModule/SET_NEW_TODO', value);
      }
    }
  },
  methods: {
    ...mapActions('todoModule', ['addTodo'])
  }
};
</script>

 

컴포넌트 사용

 

<!-- src/App.vue -->

<template>
  <div id="app">
    <h1>할 일 목록</h1>
    <TodoList />
  </div>
</template>

<script>
import TodoList from './components/TodoList.vue';

export default {
  components: {
    TodoList
  }
};
</script>

블로그의 정보

생각보다 실천을

yjym33

활동하기