<Vue 3와 타입스크립트로 배우는 프런트엔드 개발> ch5 ~ ch7

2025. 3. 6.·🎨 프론트엔드 공부/Vue & Nuxt

ch5. 양방향 데이터 바인딩과 기타 디렉티브

v-model: 템플릿 변수(예 - ref)와 컨트롤 값(input의 value) 간 양방향 데이터 바인딩

- v-bind:value와 v-input을 조합하여 v-model로 간단히 표현

 

v-model 수식어

- lazy: input 대신 change 이벤트로 양방향 데이터 바인딩 수정

- number: 입력값을 숫자로 취급

- trim: 입력값의 전후 공백 제거

 

Input 이벤트와 Change 이벤트 비교

- onInput: input 마다 이벤트 발생 -> v-model

- onChange: input이 blur 되면 이벤트 발생 -> v-model.lazy

- 예시

<template>
  <div>
    <div>
      <h2>v-model</h2>
      <input v-model="textOnInput" type="text" />
      <p>입력 문자열: {{ textOnInput }}</p>
    </div>
    <div>
      <h2>v-model.lazy</h2>
      <input v-model.lazy="textOnChange" type="text" />
      <p>입력 문자열: {{ textOnChange }}</p>
    </div>
    <div>
      <h2>v-mode.trim</h2>
      <input v-model.trim="trimmedText" type="text" />
      <p>입력 문자열: {{ trimmedText }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
const textOnInput = ref("");
const textOnChange = ref("");
const trimmedText = ref("");
</script>

 

v-html: html 문자열을 그대로 표시

- html 문자열을 element 컨텐츠로 넣음

- XSS 공격에 취약하여 사용하지 않는 것이 좋음

- 예시

<template>
  <div>
    <div>{{ htmlStr }}</div>
    <div v-html="htmlStr"></div>
  </div>
</template>

<script setup lang="ts">
const htmlStr = ref(`<a href="https://www.naver.com/">네이버<a/>`);
</script>

 

v-once: 데이터 바인딩을 한 번만 수행

- 상태값 변화에 따라 UI를 바꾸지 않음

 

v-cloak: 렌더링이 끝날 때까지 머스태시 구문 숨김

- Nuxt의 <ClientOnly>와 비슷한듯

 

ch6. 제어 디렉티브

조건 분기 사용 시 <template> 태그를 사용하기(<div> 를 쓰고 싶지 않을 때)

- React의 <fragment> 에 key 넣는 것처럼 불필요한 div를 피할 수 있음

<template>
  <div>
    <p>
      점수는 {{ randomNumber }}점
      <template v-if="randomNumber > 80">
        으로 매우 우수합니다
        <span style="color: red">대단해요!</span>
      </template>
    </p>
  </div>
</template>

<script setup lang="ts">
const randomNumber = computed(() => Math.round(Math.random() * 100));
</script>

 

v-show: 렌더링은 하되, display: none 효과 부여

- 특정 컴포넌트를 빈번하게 노출 전환할 때 사용하면 좋다(렌더링 자체는 되기 때문에 표시 전환 비용이 낮음)

- <template> 태그에는 v-show 사용 불가

<template>
  <div>
    <div>
      v-show 사용
      <p v-show="showOrNot">조건이 부합하여 표시</p>
    </div>
    <div>
      v-if 사용
      <p v-if="showOrNot">조건이 부합하여 표시</p>
    </div>
  </div>
</template>

<script setup lang="ts">
const randomNumber = computed(() => Math.round(Math.random() * 100));
const showOrNot = computed(() => randomNumber.value >= 80);
</script>

 

v-for 객체 순회

- 배열 뿐만 아니라 객체 리터럴도 v-for 로 순회할 수 있다

- value, key, index 순으로 참조하면 된다

- v-for 사용 시 index는 key에 적합하지 않다(대상 배열이 바뀌면 렌더링 시 바뀔 수 있으므로 완전히 고유하지 않음)

- 예시1

<template>
  <div>
    <ul>
      <li v-for="(val, key, idx) in cocktailRef" :key="val">
        {{ idx + 1 }}: ID가 {{ key }}인 칵테일은 {{ val }}
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
const cocktailRef = ref({
  2345: "화이트 레이디",
  4412: "블루 하와이",
  6792: "뉴욕",
});
</script>

 

- 예시2

< dl > : description list -> 주로 용어 정의를 위해 사용 e.g. 사전

< dt >: description term

< dd >: description detail

<template>
  <dl>
    <template v-for="(val, key, idx) in cocktailRef" :key="key">
      <dt>{{ idx + 1 }}. {{ key }}</dt>
      <dd>{{ val }}</dd>
    </template>
  </dl>
</template>

<script setup lang="ts">
const cocktailRef = ref({
  id: 2345,
  name: "White Lady",
  price: 1200,
  recipe: "진 30ml + 쿠앵트로 15ml + 레몬과즙 15ml",
});
</script>

 

v-for Map 순회

- Map 객체를 v-for 로 순회할 수 있다

- v-for 내에서 key, value 순으로 참조한다

<template>
  <div>
    <ul>
      <li v-for="[id, cocktailName] in cocktailListRef" :key="id">
        ID가 {{ id }}인 칵테일은 {{ cocktailName }}
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
const cocktailList = new Map<number, string>();
cocktailList.set(2345, "White Lady");
cocktailList.set(4412, "Blue hawaii");
cocktailList.set(6792, "New York");
console.log(cocktailList);
const cocktailListRef = ref(cocktailList);
</script>

 

카운터 변수를 활용한 v-for 순회

- 카운터 변수는 인덱스와 다르게 1부터 시작하여 n 번을 반복한다

<template>
  <ul>
    <li v-for="r in 5" :key="r">
      반지름이 {{ r }} 인 원의 둘레 길이: {{ 2 * r * Math.PI }}
    </li>
  </ul>
</template>

 

ch7. 스크립트 블록 활용

감시자(watcher)

- watchEffect

- watch

 

watchEffect: 반응형 변수의 변화를 모니터링

- 콜백함수 내부의 모든 반응형 변수를 감지하여, 반응형 변수의 값이 변경되면 콜백함수 실행

- 최초에 1번 콜백 함수가 실행됨

 

watch: 감시 대상을 명시

- 값의 변화를 감지할 반응형 변수를 콜백함수 앞에 명시

- 기본값은 최초 1번 콜백 함수를 실행하지 않음, { immediate: true } 옵션을 주면 watchEffect처럼 즉시 실행시킬 수 있음

- 변경 전후의 값을 알 수 있음

 

라이프사이클 훅

<template>
  <div>
    <div>세로 {{ heightRef }}, 가로 {{ widthRef }}인 사각형의 면적은 {{ area }}</div>
    <button @click="change">값을 변경</button>
  </div>
</template>

<script setup lang="ts">
import type { DebuggerEvent } from "vue";

const heightRef = ref(Math.ceil(Math.random() * 10));
const widthRef = ref(Math.ceil(Math.random() * 10));

const area = computed(() => heightRef.value * widthRef.value);
const change = () => {
  heightRef.value = Math.ceil(Math.random() * 10);
  widthRef.value = Math.ceil(Math.random() * 10);
};

onBeforeMount(() =>
  console.log(`beforeMount called: ${heightRef.value} * ${widthRef.value}`),
);

onMounted(() => console.log(`mounted called: ${heightRef.value} * ${widthRef.value}`));

onBeforeUpdate(() =>
  console.log(`beforeUpdate called: ${heightRef.value} * ${widthRef.value}`),
);

onUpdated(() => console.log(`updated called: ${heightRef.value} * ${widthRef.value}`));

onRenderTracked((event: DebuggerEvent) => {
  console.log(`renderTracked called: ${heightRef.value} * ${widthRef.value}`);
  console.log("🚀 ~ onRenderTracked ~ event:", event);
});

onRenderTriggered((event: DebuggerEvent) => {
  console.log(`renderTriggered called: ${heightRef.value} * ${widthRef.value}`);
  console.log("🚀 ~ onRenderTriggered ~ event:", event);
});
</script>

 

beforeCreate: Vue 애플리케이션의 시작 직후, 초기화 처리 전

 

created: Vue 애플리케이션 초기화 처리 후

 

beforeMount: 컴포넌트의 해석 처리 후 결정한 DOM을 렌더링하기 직전

 

mounted: DOM 렌더링이 완료되고 표시 상태가 된 시점, 즉, mounted 상태가 된 시점

 

beforeUpdate: 반응형 데이터가 변경되고 DOM을 리렌더링하기 직전

 

updated: DOM의 리렌더링이 완료된 시점

 

beforeUnmount: 컴포넌트의 DOM의 숨김 처리를 시작하기 직전

 

unmounted: 컴포넌트의 DOM의 숨김 처리가 완료된 시점, 즉 unmounted 상태가 된 시점

 

errorCaptured: 하위 컴포넌트를 포함하여 에러를 감지한 시점

 

renderTracked: 반응형 변수에 처음 접근이 발생한 시점

- 각 반응형 변수에 접근될 때마다 콜백이 실행됨 (예 - 반응형 변수 갯수가 n개이면 n번 콜백이 실행됨)

 

renderTriggered: 반응형 변수가 변경된 것을 감지하고 해당 변수에 접근이 있는 시점

 

activated: 컴포넌트가 더 이상 대기 상태가 아니게 된 시점

 

deactivated: 컴포넌트가 대기 상태가 된 시점

 

DebuggerEvent: Vue에서 디버깅용으로 지원하는 이벤트 객체

- 주요 props

effect: ReactiveEffect, target: RefImpl

Vue 라이프사이클

 

2) Vue 애플리케이션이 초기화되면 스크립트 블록 내부의 코드가 실행되고 ref, computed 변수 및 함수 등이 준비됨

3) 템플릿 블록의 코드를 분석하여 DOM 구조 결정

4) DOM 렌더링

5) mounted: 화면에 보이는 상태

6) 리렌더링 끝나면 다시 mounted 상태로 돌아감

 

<script> 내부의 setup(): Vue3의 Composition API에서 반응형 값을 사용하기 위해 꼭 명시해야 함

- 명시하지 않으면 Options API 방식을 사용하고 defineComponent 메서드 내부의 setup() 내부에 작성해야 함

'🎨 프론트엔드 공부/Vue & Nuxt' 카테고리의 다른 글
  • <Vue 3와 타입스크립트로 배우는 프런트엔드 개발> ch8 ~ ch9
  • <Vue 3와 타입스크립트로 배우는 프런트엔드 개발> ch1 ~ ch4
  • [Nuxt] 형제 컴포넌트끼리 데이터 공유하기
  • [Nuxt] composables, utils, types 폴더의 auto import 사용하기
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (510)
      • 🎨 프론트엔드 공부 (247)
        • JS & TS (86)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
<Vue 3와 타입스크립트로 배우는 프런트엔드 개발> ch5 ~ ch7
상단으로

티스토리툴바