Vue

지니씨·2023년 7월 27일
0

프론트엔드

목록 보기
83/86
  • create-vue로 생성된 공식 설정은 vite, vitest(단위 테스트 프레임워크)
  • 순수 로직 재사용 시 컴포저블 사용 / 로직과 시각적 레이아웃 모두 재사용할 때 컴포넌트 사용
  • setup() 함수
    : 컴포넌트 인스턴스가 생성되기 전 실행
    : 컴포넌트의 상태(data), 메서드(methods), 생명주기 훅(lifecycle hooks) 등을 정의하는 역할
  • 컴포넌트 생명주기 훅(onMounted(), onUpdated(), onUnmounted())
  • Reactive State (반응형 상태)
    reactvie(), ref() 함수를 사용하여 상태를 정의하면 해당 상태가 변경될 때 화면이 자동으로 업데이트 됨
  • computed() (Computed Properties, 계산된 속성)
    : 의존하는 상태가 변경될 때마다 자동으로 다시 계산 됨
    : 캐싱
    : 변수의 값이 한 번 설정되고 그대로 유지되는 경우에는 일반 변수 사용
    : 상태 변화에 따라 화면이 다시 렌더링되지 않는 경우 일반 변수 사용
  • watch(), watchEffect()
  • props: 부모 -> 자식
    emit: 자식 -> 부모
    v-model: 양방향 바인딩
    provide, inject: 부모 -> 자식(깊이 상관 없음)

v-model vs project&inject

  • v-model
    • <input>, <textarea>, <select> 요소에서만 사용 가능
    • 양방향 데이터 바인딩을 위해 사용되며, 부모와 자식 컴포넌트 간의 상태를 공유하는 데 적합
    • 주로 사용자 지정 컴포넌트 내에서 컴포넌트의 상태나 데이터를 부모 컴포넌트와 공유하고 싶을 때 v-model을 사용
    • 되도록 단일값만 사용
  • project & inject
    • provide와 inject는 데이터 공유를 위해 사용되며
    • 주로 컴포넌트 트리의 다른 부분에 데이터를 제공하고 공유하는 데 적합

slot

computed vs watch

  • 공통
    : Vue 인스턴스 내에 정의된 데이터 값에 변경이 일어나는지를 감시하고 변경될 때마다 정의된 함수 실행
  • computed
    : 기존에 정의된 데이터 값을 기반으로 새로운 데이터 값을 활용하기 위해 사용
  • watch
    : watch에 정의된 데이터 값 하나만을 감시하기 위한 용도
    : reactive value(ref, reactive, computed)가 변경될 때마다, 특정 함수(사이드 이펙트를 포함한 함수)를 실행하고 싶다면 watch 사용
    : watch는 computed의 대안이 아님
    (watch 함수 내에서 다른 reactive property의 값을 설정한다면 computed 사용
    (watch 함수 내에서 무언가를 반환하려한다면 computed 사용)
    : 실제 데이터 변경이 일어나기 전까지는 실행 X, 초기에 실행되지 X

watch vs watchEffect

  • watch는 이전값과 변경된 값을 알 수 있지만 watchEffect는 알 수 없다.
  • watch는 감시 대상을 지정해야만 하지만 watchEffect는 함수 안에서 참조되는 변수만 감시한다.(computed와 유사)
  • watch와 다르게 watchEffect는 "즉시" 실행된다.
  • watchEffect는 데이터의 변화를 추적하는 것이기 때문에 slots의 내부 구조 변경에는 반응하지 않을 수 있습니다.

shallowRef vs markRaw

  • 특정 데이터를 일회성이나 정적인 데이터로 취급하고자 할 때 유용
  • shallowRef
    • 주어진 값에 대한 얕은(Shallow) 리액티브 참조 생성
    • 해당 객체의 내부 속성이 변경되어도 해당 내부 속성에 대한 반응이 일어나지 않음 (.value 접근 까지만 반응형)
    • 주로 객체나 배열과 같은 복합 데이터 구조를 다룰 때 사용
    • 내부 깊은 곳까지의 변환은 피하고 루트 수준에서만 반응형을 유지하려면, shallowReactive()를 사용
  • markRaw
    • 주어진 값을 리액티브에서 제외
    • 특정 객체나 값이 리액티브 시스템에 의해 관찰되지 않도록 하려는 경우 유용

컴포저블

  • 컴포저블은 Vue 컴포지션 API를 활용하여 상태 저장 로직를 캡슐화하고 재사용하는 함수

일반변수 vs ref vs 일반함수 vs computed vs reactive

  • 일반변수
  • ref
    :
  • 일반함수
    : 계산 결과 캐싱 X (함수 호출하는대로 실행)
  • computed
    : 연결되는 값이 변경되면 자동으로 새로운 값 계산, 화면에 반영
    : 계산 결과 캐싱 O (중복호출 방지)
    : 기본적으로 readonly이며 readonly로 사용하자
  • reactive
    : 객체 또는 배열을 반응형으로 만듬

Vue3 공식문서

https://v3-docs.vuejs-korea.org/guide/introduction.html

컴포지션 API

<script setup>
import { ref, onMounted } from 'vue'

// 반응적인 상태의 속성
const count = ref(0)

// 속성 값을 변경하고 업데이트 할 수 있는 함수.
function increment() {
  count.value++
}

// 생명 주기 훅
onMounted(() => {
  console.log(`숫자 세기의 초기값은 ${ count.value } 입니다.`)
})
</script>

<template>
  <button @click="increment">숫자 세기: {{ count }}</button>
</template>

핵심 가이드

반응형 기초

  • 반응 상태를 변경하면 DOM이 자동으로 업데이트됨
  • 반응 상태를 변경하면 DOM이 자동으로 업데이트되지만 DOM 업데이트는 동기적으로 적용되지 않음
  • 상태 변경 후, DOM 업데이트가 완료될 때까지 기다리려면 nextTick() 전역 API 사용 가능
  • reactive()
    : 객체 또는 배열을 반응형으로 만들 수 있음
    : 반환 값은 원본 객체와 같지 않고, 원본 객체를 재정의한 프락시(Proxy)
    : Vue의 반응형 시스템 작업 시 가장 좋은 방법은 상태를 재정의한 프락시만 사용 (원본 객체를 변경해도 업데이트 트리거 X)
    : 제한 사항 1. 객체, 배열, 컬렉션 유형(Map, Set 같은)에만 동작 (string, number, boolean 과 같은 기본형에서 사용 X)
    : 제한 사항 2. 객체를 쉽게 교체하지 못함 (반응형 객체의 속성을 로컬 변수에 할당, 분해 할당, 함수에 전달하면 반응형 연결 끊어짐)
  • ref()
    : reactive()의 제한사항 해결하기 위함
    : 받은 인자를 .value 속성을 포함하는 ref 객체에 래핑 후 반환 (template에서는 자동으로 언래핑되어 .value없이 사용 가능)

계산된 속성

  • 반응형 데이터를 포함하는 복잡한 논리의 경우 계산된 속성 사용
  • 캐싱, 계산된 속성은 기본적으로 getter 전용 / 수정 가능한 계산된 속성이 필요한 경우 getter 와 setter 모두 제공하여 속성 만들 수 있음

Form 입력 바인딩

  • v-model은 모든 폼 엘리먼트에서 감지되는 value, checked, selected 속성 값을 무시한다. reactivity API를 사용하여 JavaScript에서 초기 값을 선언해야 한다.
  • IME가 필요한 언어(중국어, 일본어, 한국어 둥)의 경우 IME 구성 중에 v-model이 업데이트되지 않는 것을 알 수 있다. 이러한 업데이트에도 응답하려면 v-model 대신 직접 input 이벤트리스너와 value 바인딩을 사용해 기능을 구성해야 한다. ??
  • select 엘리먼트가 선택되지 않은 상태로 렌더링되면 ios에서는 변경 이벤트를 발생시키지 않아 사용자가 첫 번째 항목을 선택할 수 없게 된다. 예시처럼 비활성화된 옵션에 빈 값을 제공하는 것이 좋다.
  • *.* 수정자

생명 주기 훅
아래 세 생명 주기가 가장 많이 사용 됨

  • onMounted (컴포넌트 초기 렌더링, DOM 노드 생성이 완료된 후 코드 실행)
  • onUpdated
  • onUnmounted

감시자

  • computed(), method로 대부분 커버?
  • 상태 변경에 대한 반응으로 사이드이펙트(ex. DOM변경, 비동기 작업의 결과를 기반으로 다른 상태 변경 등)를 수행해야 하는 경우 Watchers 활용
  • wtach()
    : 반응형 속성이 변경될 때마다 함수 실행 (source가 변경된 뒤에 콜백 호출)
    : Deep Watchers (감시된 객체의 모든 중첩 속성을 탐색하기에 성능에 영향을 주는지 고려해서 사용해야 함)
    : Eager Watchers (immediate:true옵션을 전달하면 워처의 콜백이 즉시 실행된 다음 source가 변경되면 다시 실행 됨)
  • watchEffect()
    : ex. 초기 데이터를 가져온 다음 관련 상태가 변경될 때마다 데이터를 다시 가져오길 원할 때
    : // immediate: true 옵션 설정시와는 뭐가 다른거지?
  • watch()는 명시적으로 감시된 소스(첫번째 인자)만 추적, 콜백 내에서 조회하는 항목은 추적X, 소스가 실제로 변경된 경우에만 콜백 실행
  • watchEffect()는 동기적(sync) 실행중 조회되는 모든 반응형 속성 자동으로 추적, 콜백 실행되어야 하는 시기가 덜 명시적
  • 개발자가 생성한 워쳐 콜백은 Vue 컴포넌트가 업데이트되기 전에 실행 됨, 워쳐 콜백 내에서 DOM 접근하면 DOM이 Vue에 의해 업데이트되기 전 상태임, 워쳐 콜백에서 Vue에 의해 업데이트된 후의 DOM을 접근하려면 flush:'post' 옵션 지정해줘야 함.
  • watchPostEffect()
    : flush: 'post' 옵션이 적용된 watchEffect()
    : flush: 'pre'|'post' 옵션은 콜백을 버퍼링하여, 동일한 "틱(tick)"에서 여러 번 상태 변경이 되더라도 마지막에 한 번만 호출
  • setup() 또는 <script setup> 내부에서 동기적으로 선언된 감시자는 해당 컴포넌트 인스턴스에 바인딩되며, 해당 컴포넌트가 마운트 해제되면 자동으로 중지 된다. 대부분의 경우 감시자 해제에 대해 고민할 필요가 없다. 감시자가 비동기 콜백에서 생성되는 겨우 감시자는 컴포넌트에 바인딩되지 않으며 누수를 방지하기 위해 수동으로 중지해줘야하지만, 감시자를 비동기식으로 생성하는 경우는 거의 없고 가능하면 동기식 생성을 해야한다.

템플릿 참조

  • Vue의 선언적 렌더링 모델은 개발자가 직접 DOM에 접근 해야하는 대부분을 추상화하지만, 개발자가 DOM 엘리먼트에 직접 접근해야 하는 경우가 여전히 있을 수 있다. 이럴때 ref를 사용한다.

컴포넌트 기초

  • 싱글 파일 컴포넌트(SFC)라고 하는 .vue 확장자를 사용하는 전용 파일에 각 Vue 컴포넌트 정의
  • props는 컴포넌트에 등록할 수 있는 사용자 정의 속성
  • 이벤트 청취 ... ?
  • slot
  • 동적 컴포넌트 (ex. tab)
  • DOM 템플릿 작성시 주의 사항
    : JS에서 camelCase, HTML에서 kebab-case
    : <MyComponent/>, <my-component></my-component>
    : ul, ol, table, select와 같은 일부 HTML 엘리먼트에는 내부에 표시할 수 있는 엘리먼트에 대한 제한이 있음 / li, tr, option 과 같은 일부 엘리먼트는 특정 다른 엘리먼트 내부에만 사용할 수 있음 => is속성으로 해결

컴포넌트 심화

  • <PascalCase />로 컴포넌트 등록, template 태그 내에서는 <kebab-case></kebab-case> 로 사용
  • props: 부모 -> 자식
  • emit: 자식 -> 부모
    : 네이티브 이벤트(예: click)가 emits 옵션에 정의된 경우 리스너는 이제 컴포넌트에서 발생하는 click 이벤트만 수신 대기하고 네이티브 click 이벤트에 더 이상 응답하지 않습니다.

v-model: 양방향 바인딩

<!-- 방법1. CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

<!-- 방법2. CustomInput.vue -->
<script setup>
import { computed } from 'vue'

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const value = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  }
})
</script>

<template>
  <input v-model="value" />
</template>
<!-- App.vue -->
<CustomInput v-model="searchText" />

폴스루(fallthrough:대체) 속성 : class, style, id ?

슬롯(slot)
: <slot> 태그 사이에 배치하면 대체 컨텐츠
: 슬롯에 이름 지정 가능 v-slot 의 전용 단축 문법은 #
: 슬롯 컨텐츠는 자식 컴포넌트의 상태에 접근 불가능 / 슬롯에 props 전달 가능
: 범위가 지정된 슬롯?

Provide(제공) / Inject(주입)
: 하위 트리의 모든 컴포넌트는 깊이에 관계없이 상위 체인의 컴포넌트에서 제공(provide)하는 의존성을 주입(inject)할 수 있다.
: provide(Key:String|Symbol, value:refs와 같은 반응 상태를 포함한 모든 유형) / 주입 대상 컴포넌트에서 데이터 업데이트해아 하는 경우, 상태 변경을 담당하는 함수까지 함께 제공 / 주입된 컴포넌트에 의해 데이터가 변경될수 없도록 하려면, 제공된 값을 readonly()로 래핑 / 심볼키 사용하는게 좋음
: inject(Key, 기본값)

defineAsyncComponent(비동기 컴포넌트)

  • Promise를 반환하는 로더 함수
  • ES 모듈 동적으로 가져오기도 Promise를 반환하므로, 대부분의 경우 defineAsyncComponent와 함께 사용합니다.

TypeScript

  • 개발 환경
    : Vite 기반 설정을 사용하면 개발 서버와 번들러가 트랜스파일만 수행, 타입 검사 X (타입스크립트를 사용하는 경우에도 Vite dev 서버가 빠른 속도로 유지됨)
    : Volar (Vue2용 공식 VSCode extension인 Vetur 대체, Vetur 설치되어 있는 경우 Vue3 프로젝트에서 비활성화)
    : Vue CLI 타입스크립트 지원 하지만 권장 X

  • 일반 사용
    : defineComponent()를 사용해 컴포넌트를 정의해야 타입스크립트가 컴포넌트 옵션 내에서 타입을 올바르게 추론할 수 있음
    : <script>태그에 lang="ts"속성 추가

  • 컴포넌트 Props 작성 : defineProps

// 타입 기반 선언(type-based declaration)
export interface Props {
  msg?: string
  labels?: string[]
}

// withDefaults로 프로퍼티의 기본값을 선언
const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})
  • 컴포넌트 Emits 작성 : defineEmits
  • ref(), reactive(), computed() 타입 적용
  • 이벤트 핸들러 타입 지정
  • Provide, Inject 타입 지정 ?
  • 템플릿 Refs 타입 지정
  • 컴포넌트 템플릿 Template Refs에 타입 지정
<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'

const modal = ref<InstanceType<typeof MyModal> | null>(null)

const openModal = () => {
  modal.value?.open()
}
</script>

API (Composition API, 빌트인)

Composition API

  • 컴포넌트의 setup옵션 사용법, 싱글 파일 컴포넌트(*.vue)에서 컴포지션 API 사용하는 경우 <script setup> 사용 권장
  • ref()
  • computed()
    : getter 함수를 사용하며 getter로부터 반환된 값을 읽기 전용 반응형 ref객체로 반환한다.
    : getset 함수가 있는 객체를 사용하면 쓰기가 가능한 ref 객체를 반환한다.

빌트인

싱글 파일 컴포넌트

  • <script setup>
  • <script setup>은 싱글 파일 컴포넌트(SFC) 내에서 컴포지션 API를 더 쉽게 읽거나 사용하기 위한 컴파일 타임 문법
  • defineExpose

재사용성 (컴포저블, )

컴포저블

  • Vue 컴포지션 API를 활용하여 "상태 저장 로직"을 캡슐화하고 재사용하는 함수
  • 중복 로직 및 코드 재사용 & 체계화를 위해 추출
  • useCamelCase : 함수 이름 관례
  • 컴포저블에서는 ref 객체를 반환하여 반응성을 유지하면서 컴포넌트 구조화 하는게 좋음 (reactive() 대신 ref()를 독점적으로 사용)
  • Vue 2에서 사용하던 mixins 옵션 사용 지양
  • 순수 로직 재사용 시 컴포저블 사용 / 로직과 시각적 레이아웃 모두 재사용할 때 컴포넌트 사용
  • 다른 개발자가 사용할 수 있는 컴포저블 작성 시, 입력 인수가 원시 값 대신 ref나 getter인 경우 처리하는게 좋음
  • 컴포저블에서는 reactvie() 대신 ref()를 독점적으로 사용, 항상 ref 객체 반환하기

// 커스텀 디렉티브

  • 일반적으로 컴포넌트에 커스텀 디렉티브를 사용하는 것은 권장 X
  • 원하는 기능을 직접 DOM 조작을 통해서만 달성할 수 있는 경우에만 사용, 가능하면 v-bind와 같은 내장 디렉티브를 사용하여 선언적 템플릿 사용하는 것이 더 효율적이고 서버 렌더링에 친숙
  • mounted, updated에 대해 동일한 동작을 갖는 것이 일반적
  • ex. v-focus

플러그인

  • Vue에 앱 레벨 기능을 추가하는 자체 코드
  • install() 메서드에서 정의, app.use에서 사용
  • ex. i18nPlugin

빌트인 컴포넌트 (Teleport, )

// Teleport 정도 알면 될 듯?

  • <Teleport> : Modal 컴포넌트 같은 경우에서 활용
    ex.
<button @click="open = true">모달 열기</button>

<Teleport to="body" :disabled="isMobile">
  <div v-if="open" class="modal">
    <p>짜자잔~ 모달입니다!</p>
    <button @click="open = false">닫기</button>
  </div>
</Teleport>

확장하기

상태관리

  • 여러 뷰가 동일한 상태에 따라 달라질 수 있습니다.
    : 공유 상태를 공통 조상 컴포넌트로 "끌어올린" 다음 props로 전달
  • 서로 다른 뷰의 기능이 동일한 상태를 변경시킬 필요가 있을 수 있습니다.
    : 템플릿 refs를 통해 직접적인 부모/자식 인스턴스에 도달하거나, 발송(emit)된 이벤트를 통해 상태의 여러 복사본을 변경 및 동기화하려는 것과 같은 솔루션에 의존하는 경우가 많습니다. 이러한 패턴은 모두 깨지기 쉽고 빠르게 유지 관리할 수 없는 코드로 이어집니다.
  • Pinia (Vuex대체하는 공식 상태관리 라이브러리)

테스팅

  • 테스트 유형 : 단위, 컴포넌트, End-toEnd
  • 단위 테스트
    : 함수, 클래스, 컴포저블이 의도한 입출력과 사이드이펙트를 생성하는지
    : 일반적으로 UI 렌더링, 네트워크 요청 또는 기타 환경 문제를 포함하지 않는 자체적으로 해야 할 일에 대한 논리: , 컴포넌트, 클래스, 모듈 또는 함수에 적용
    : 일반적으로 Vue와 관련이 없는 일반 JavaScript/TypeScript 모듈
    : Vue 관련 기능의 단위 테스트1 - 컴포저블 테스트 ()
    : Vue 관련 기능의 단위 테스트1 - 컴포넌트 (Whitebox, Blackbox)
    : vitest(추천), peeky, Jest
  • 컴포넌트 테스트
    : 마운트, 렌더링, 상호작용 의도대로 작동 확인
    (컴포넌트의 props, 이벤트, 제공하는 슬롯, 스타일, 클래스, 생명 주기 훅 등과 관련된 문제 포착)
    : 각 Vue 컴포넌트에는 자체 스팩 파일이 있는것이 좋음
    : 내부 구현 세부 사항보다는 컴포넌트의 공개 인터페이스에 중점(이벤트 발생, props, 슬롯)
    : "컴포넌트가 어떻게 작동하는지가 아니라, 어떤 작동을 하는지" 테스트
    : Vitest(헤드리스로 렌더링되는 컴포넌트), @testing-library/vue(컴포넌트와 DOM), @testing-library/cypress(예상 동작이 스타일을 올바르게 렌더링하거나 기본 DOM 이벤트를 트리거하는 데 의존하는 컴포넌트), @uve/test-utils(Vue 전용 내부 테스트가 필요한 고급 컴포넌트를 빌드하는 경우에만 사용 권장) / Nightwatch(Vue 컴포넌트 테스트를 지원하는 E2E 테스트 러너)
  • E2E 테스트
    : 여러 페이지에 걸쳐 있는 기능 확인, 네트워크 요청 등

튜토리얼

  • Vue SFC(Single File Component)
    : HTML, CSS, JavaScript를 캡슐화한 코드 블록으로 재사용 가능한 .vue 파일
  • reactive(), ref(), {{}}
  • 속성 바인딩
    : v-bind 디렉티브 (:)
    : 바인딩된 값이 null 또는 undefined이면 엘리먼트의 속성이 제거된 상태로 렌더링 됩니다.
    : 인자없는 v-bind는 객체의 모든 속성을 대상 엘리먼트의 속성으로 묶음
  • 이벤트 리스터 : v-on (@)
  • 폼 바인딩 : `v-model₩
  • 조건부 바인딩 : v-if, v-else, `v-else-if₩
  • 리스트 렌더링 : v-for, :key
  • computed() : 반응 데이터 소스를 기반으로 .value를 계산하는 계산된 참조(ref)를 만듬
  • 템플릿 참조(ref), 컴포넌트 생명주기 훅(onMounted(), onUpdated(), onUnmounted())
  • 감시자
  • 부모 -> 자식 props (defineProps에 선언) / 자식 -> 부모 emit (defineEmits에 선언) / 부모 -> 자식 slot컴포넌트

참고

  • v-show는 초기 렌더링 비용이 더 높음, 매우 자주 전환해야 하는 경우 v-show, 실행 중 조건이 변경되지 않는 경우 v-if 사용
  • v-ifv-for함께 사용하면 v-if가 먼저 평가되기때문에 함께 사용하는 것은 권장 X



강의

command + shift + p
file icon > material icon
color theme > night owl

State of JS
https://2022.stateofjs.com/en-US/

State of Vue.js
https://www.monterail.com/state-of-vue-2021-report
Ease of integration : 점진적인 적용이 쉬움

[ Vue.js 라이브러리 생태계 ]

공식 라이브러리

  • Vue Core - 화면 렌더링 및 DOM 조작 API
  • Vue Router - 라우팅
  • Vuex - 상태 관리
  • Vue CLI - 프로젝트 설정 도구
  • Vue Devtools - 디버깅 도구
  • Nuxt - 서버 사이드 렌더링
  • Vue Test Utils - 테스트 도구

기타

  • 코딩컨벤션 - Style Guide
  • Vetur, Prettier, ESLint 와 함께

[ Vue.js 개념 ]

MVVM패턴과 Reactivity

Object.defineProperty() API를 라이브러리화 시킨게 Vue.js

[ 컴포넌트란? ]

  • 화면의 특정 영역을 재사용 가능한 형태로 구성한 코드
  • 컴포넌트에 대한 코드(HTML/JS/CSS)를 한 파일에서 관리 가능한게 SPA
// 전역 컴포넌트 - 서비스 구현시 쓸 일 없음 (컴포넌트간의 관계 모호, 재사용 한계)
Vue.component('컴포넌트 이름', 컴포넌트 내용);

// 지역 컴포넌트
new Vue({
	components: {
    	'컴포넌트 이름': 컴포넌트 내용
	}
})

Props Validation

  • 최소한 타입이라도 정의, required 까지 정의해주기

// Event Bus

  • 공식문서에서 제거 됨 / 사용 지양
  • 컴포넌트 통신의 기본 규칙을 따르지 않고 특정 컴포넌트 간에 통신하는 방법
  • 쓰고 나면 반드시 $off()로 해제. 안그러면 적체됨

컴포넌트 통신 방법 vs Event Bus

  • 위->아래 Props, 아래->위 Event Emit
  • 컴포넌트 레벨이 2단계 이하면 props, event emit 쓰는 것이 좋음
  • 토스트 팝업, 프로그레스 바와 같이 on, off 성격의 UI 컴포넌트에서는 Event Bus 활용하는 것도 좋음

Smart Watch

Computed

  • data 속성의 변화에 따라 함께 변하는 속성
  • 대부분의 케이스에서는 computed, methods로 해결 가능, watch 사용은 지양
  • watch는 데이터 호출 로직과 연관된 동작에만 사용하면서 최소한으로 사용
    ex.

템플릿 문법

  • directives : 화면의 돔 조작을 쉽게해주는 문법 (v-*)
  • 데이터 바인딩 : 뷰 인스턴스의 데이터를 화면에 연결해주는 문법

데이터 바인딩의 내부 동작 과정

Render Function

  • 개발자가 직관적인 템플릿 코드를 작성하도록 뷰 내부적으로 실행하는 함수
  • 템플릿 코드 까지 작성하면, 템플릿 변환 순서는 아래와 같음
    : Render Function 으로 변환 -> Virtual DOM 반환 -> 실제 DOM 부착

뷰 컴포넌트 스타일링 팁

  • 싱글 파일 컴포넌트의 scoped 속성 활용 (특정 컴포넌트에만 국한된 CSS코드)
  • 디자인 공통 CSS : App.vue 파일에 @import 로 적용
  • 페이지 전용 CSS : 페이지 기준 최상위 컴포넌트에 페이지 전용 공통 CSS 적용 (@import, scoped 사용)

[ Vue.js 데이터 호출 패턴 ]

axios

  • 뷰에서 가장 많이 사용되는 HTTP 통신 라이브러리
  • Promise 기반의 API 제공
  • Instance 기반의 설정 옵션 확장
  • Inteceptor를 이용한 Request, Response 전처리
  • 우수한 사용 예시 및 문서화

1. 뷰 인스턴스 라이프 사이클

  • https://vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram
  • 뷰 인스턴스가 생성되고 소멸되기까지의 생애 주기
  • 라이프 사이클 훅을 이용한 데이터 호출
    created : 컴포넌트가 생성되자마자 호출
    beforeMount 도 사용할때는 큰 차이 없음 (팀 내부적으로 규칙 정해서 사용하면 됨)

2. Router Navigation Guard

  • 뷰라우터 뷰엑스
  • nuxt asyncdata 넉스트만 가지고 있는 컴포넌트 속성 => 구현 공부
  • 뷰 라우터 : 뷰에서 페이지 이동과 관련된 API 및 속성을 제공하는 공식 라이브러리
  • 뷰 라우터 네비게이션 가드 : 특정 페이지로 진입하기 전 커스텀 로직을 반영할 수 있는 속성
  • 스토어와 라우터 네비게이션 가드를 이용한 데이터 호출
  • 스토어 - 뷰 상태 관리 라이브러리 Vuex
  • 상태란 여러 컴포넌트에서 공통으로 사용하는 data 속성
  • View -> Action -> State -> View -> Action...

[ 패턴 ]

컴포넌트 생성절차
: component 내용 작성
-> component 내용을 component 속성에 연결
-> component 태그 이름 정의
-> 태그 이름으로 사용

1. Common Approach

  • UI영역 기준으로 코드 나눠서 관리
  • 단점
    : 요구사항 변경 대응에 어려움
    : 작은 UI 변경에도 새로 컴포넌트를 생성하거나 기능 확장이 어려움

2. Component with Slots

  • 하위 컴포넌트의 표현부(태그,스타일)을 유연하게 확장할 수 있는 방법
  • slot 여러개 사용하는 방법도 있음, 2.7부터 문법 좀 바뀜
  • 마크업 구조가 변경되었다고 컴포넌트 추가할 필요 없음
  • 모달, 툴팁, 토스트 등 공통 UI 컴포넌트에 활용 / 카드, 테이블 등의 그리드 컴포넌트에도 사용 가능
  • vue create slots => 실습

3. Controlled Component

  • 상위 컴포넌트에서 하위 컴포넌트를 더 쉽게 제어할 수 있는 방법
  • 날짜 선택기, 체크박스 등의 UI 컴포넌트에서 활용도 높음

// 4. Renderless Component

  • (이런게 있다 정도만 알아둬도 될 듯)
  • UI로직을 제외하고 데이터 로직만 구분하여 관리하는 방법

5. Mixins

  • 중복되는 컴포넌트 로직을 재활용하기 위한 첫 번째 방법
  • 한 페이지에서 필요한 비지니스 로직만 남겨두고 나머지 공통 로직들은 공통으로 빼줌
  • 믹스인 사용하는 컴포넌트의 로직과 충돌나지 않게 팀내 코딩 컨벤션 선정
  • 믹스인과 컴포넌트의 로직이 충돌나면 컴포넌트의 로직이 우선순위를 가짐

// 6. High Order Component

  • (Mixins으로 충분한 듯?)
  • 중복되는 컴포넌트 로직을 재활용하기 위한 두 번째 방법
  • 데이터불러오는 로직이 list-view가 다 들고있음
  • 컴포넌트의 레벨이 깊어져서 데이터 전달이 번거로워지지 않게 주의



SSR

Nuxt

  • Nuxt는 Vue.js로 빠르게 웹을 제작할 수 있게 도와주는 프레임워크입니다. 웹 애플리케이션을 제작할 때 필요한 뷰엑스, 라우터, Axios와 같은 라이브러리들을 미리 구성하여 싱글 페이지 애플리케이션(Single Page Application), 서버 사이드 렌더링(Server Side Rendering), 정적 웹 사이트(Static Generated Website)를 쉽게 제작할 수 있습니다.
  • https://day0404.tistory.com/8
<NuxtLayout>
   <NuxtPage />
</NuxtLayout>

ClientOnly

  • Nuxt.js에서 "client-only" 태그를 사용하는 것은 특정 컴포넌트나 코드 블록을 클라이언트 측에서만 실행되도록 지정하는 데 사용
  • 일반적으로 서버 측에서 실행할 필요가 없는 코드 또는 브라우저 API를 사용하는 코드와 같은 경우에 유용
  • "client-only" 태그를 사용하는 것이 좋은 방향인지 여부는 프로젝트의 특정 요구사항과 사용 사례에 따라 다를 수 있음. 일반적으로 다음과 같은 상황에서 "client-only" 태그를 사용하는 것이 좋습니다:
    • 브라우저 API 사용: 브라우저 API를 사용하는 코드를 실행할 때, 이것은 클라이언트 측에서만 작동하므로 "client-only" 태그를 사용하여 이를 명시적으로 지정하는 것이 좋음
    • 성능 최적화: 서버 측에서 렌더링되는 것이 필요하지 않은 경우, "client-only" 태그를 사용하여 해당 컴포넌트를 클라이언트 측에서만 렌더링하여 초기 로드 속도를 향상
    • 서버 사이드 렌더링에서 오류 발생: 일부 코드 블록이 서버 사이드 렌더링 도중 에러를 발생시키는 경우, 이를 회피하기 위해 "client-only" 태그를 사용하여 해당 코드 블록을 클라이언트 측에서만 실행할 수 있음
  • 그러나 주의할 점은 "client-only" 태그를 남용하지 않는 것입니다. 서버 측 렌더링의 이점을 활용하기 위해서는 가능한 한 많은 코드를 서버 측에서 실행하는 것이 이상적입니다. 따라서 "client-only"를 사용하는 것은 코드가 반드시 클라이언트 측에서 실행되어야 하는 경우에만 사용하는 것이 중요합니다.



Router

  • 웹페이지간의 이동방법
  • 페이지를 이동할때 서버에 요청하여 새로 갱신하는 것이 아니라 미리 해당 페이지를 받아 놓고 페이지 이동시 클라이언트의 라우팅을 이용하여 화면 갱신 (이러한 방식을 SPA라고도 함)

Nuxt Routing

Vue Router



Test

Vitest

mount 와 shallowMount 차이
https://jh-7.tistory.com/20

profile
하루 모아 평생 🧚🏻

1개의 댓글

comment-user-thumbnail
2023년 7월 27일

많은 도움이 되었습니다, 감사합니다.

답글 달기