Basic Syntax(2)

뚝딱뚝딱·2023년 11월 6일
0

Vue

목록 보기
3/6
post-thumbnail

1. Computed Property

computed()

  • 계산된 속성을 정의하는 함수

  • 미리 계산된 속성을 사용하여 템플릿에서 표현식을 단순하게 하고 불필요한 반복 연산을 줄임

  • computed 기본 예시, 적용

<body>
      <div id="app">
        <h2>남은 할 일</h2>
            // 1번째 방법
        <p>{{ restOfTodos }}</p>
            // 메서드 활용방법
        <p> {{ getRestofTodos() }}</p>
      </div>
    
      <script src="<https://unpkg.com/vue@3/dist/vue.global.js>"></script>
      <script>
    // computed 적용
        const { createApp, ref, computed } = Vue
    
        const app = createApp({
          setup() {
          // 할 일이 남았는지 여부에 따라 다른 메시지 출력하기
            const todos = ref([
              { text: 'Vue 실습' },
              { text: '자격증 공부' },
              { text: 'TIL 작성' }
            ])
            const restOfTodos = computed(() => {
              return todos.value.length > 0 ? '아직 남았다' : '퇴근!'
            })
    
            const getRestofTodos = function () {
              return todos.value.length > 0 ? '아직 남았다' : '퇴근!'
            }
    
            return {
              todos,
              restOfTodos,
              getRestofTodos
            }
          }
        })
    
        app.mount('#app')
      </script>
    </body>
  • 반응성 데이터를 포함하는 복잡한 로직의 경우 computed를 활용하여 미리 값을 계산

computed 특징

  • 반환되는 값은 computed ref 이며 일반 refs와 유사하게 계산된 결과를 .value로 참조할 수 있음(템플릿에서는 자동으로 wrapping 되기 때문에 .value 생략 가능)
  • computed 속성은 의존된 반응형 데이터를 자동으로 추적
  • 의존하는 데이터가 변경될 때만 재평가
    - restOftodos의 계산은 todos에 의존하고 있음
    • 따라서 todos가 변경될 때만 resOftodos가 업데이트 됨

Computed vs Methods

computed 속성 대신 method 로도 동일한 기능을 정의할 수 있음

  • 두 가지 접근 방식은 실제로 완전히 동일

computed 와 method의 차이

  • computed 속성은 의존된 반응형 데이터를 기반으로 캐시 된다. ( 매번 재평가하지 않는다)
  • 의존하는 데이터가 변경된 경우에만 재평가됨
  • 즉, 의존된 반응형 데이터가 변경되지 않는 한 이미 계산된 결과에 대한 여러 참조는 다시 평가할 필요 없이 이전에 계산된 결과를 즉시 반환
  • 💡 반면, method 호출은 다시 렌더링이 발생할 때마다 항상 함수를 실행

캐시(Cache)

  • 데이터나 결과를 일시적으로 저장해두는 임시 저장소
  • 이후에 같은 데이터나 결과를 다시 계산하지 않고 빠르게 접근할 수 있도록 함
    ex. 웹 페이지의 캐시 데이터 -> 페이지 일부 데이터를 브라우저 캐시에 저장 후 같은 페이지에 다시 요청 시 모든 데이터를 다시 응답 받는 것이 아닌 캐시 된 데이터를 사용하여 더 빠르게 웹 페이지를 렌더링

computed 와 method 의 적절한 사용처

computed

  • 의존하는 데이터에 따라 결과가 바뀌는 계산된 속성을 만들 때 유용
  • 동일한 의존성을 가진 여러 곳에서 사용할 때 계산 결과를 캐싱하여 중복 계산 방지

    의존된 데이터가 변경되면 자동으로 업데이트

method

  • 단순히 특정 동작을 수행하는 함수를 정의할 때 사용
  • 데이터에 의존하는지 여부와 관계없이 항상 동일한 결과를 반환하는 함수

    호출해야만 실행됨
    💡 무조건 computed만 사용하는 것이 아니라 사용목적과 상황에 맞게 computed와 method를 적절히 조합하여 사용


2. Conditional Rendering

Conditional Rendering

v-if

  • 표현식의 T/F를 기반으로 요소를 조건부로 렌더링
  • 'v-else' directive를 사용하여 v-if 에 대한 else 블록을 나타낼 수 있음
    const app = createApp({
      setup() {
        const isSeen = ref(true)

        return {
          isSeen,
        }
      }
    })
   <!-- if else -->
    <p v-if="isSeen">true일때 보여요</p>
    <p v-else>false일때 보여요</p>
    <button @click="isSeen = !isSeen">토글</button>

  • 다른 것들은 아예 렌더링도 되지 않았음을 볼 수 있음
<!-- else if -->
    <div v-if="name === 'Alice'">Alice입니다</div>
    <div v-else-if="name === 'Bella'">Bella입니다</div>
    <div v-else-if="name === 'Cathy'">Cathy입니다</div>
    <div v-else>아무도 아닙니다.</div>

  • 다른 것들은 아예 렌더링도 되지 않았음을 볼 수 있음


HTML <template> element

  • 페이지가 로드될 때 렌더링 되지 않지만 JavaScript를 사용하여 나중에 문서에서 사용할 수 있도록 하는 HTML을 보유하기 위한 메커니즘
  • 보이지 않는 wraaper 역할

v-if vs v-show

  • 둘다 조건부 렌더링이라는 공통점!
    v-show
  • 표현식 값의 T/F를 기반으로 요소의 가시성(visibility)을 전환
    <!-- v-show -->
    <div v-show="isShow">v-show</div>

v-show는 display: none 으로 렌더링은 한다!!

v-if(Cheap initial load, expensive toggle)

  • 초기 조건이 false인 경우 아무 작업도 수행하지 않음
  • 토글 비용이 높음

v-show(Expensive initial load, cheap toggle)

  • 초기 조건에 관게 없이 항상 렌더링
  • 초기 렌더링 비용이 더 높음
  • 토글이 되어있는 상태에서는 싸게 먹힌다

=> 무언가를 매우 자주 전환해야 하는 경우에는 v-show를 ,
실행중에 조건이 변경되지 않는 경우에는 v-if 를 권장


3. List Rendering

  • 반복 가능한 애들 렌더링

v-for

  • 소스 데이터(Array, Object, number, string, lterable)를 기반으로 요소 또는 템플릿 블록을 여러 번 렌더링
  • v-for는 alias in expression 형식의 특수 구문을 사용하여 반복되는 현재 요소에 대한 별칭(alias)을 제공
  • 인덱스(객체에서는 키)에 대한 별칭을 지정할 수 있음
  • 위치는 지정되어있음
  • alias를 하나만 하면 => 값이 출력되고
  • 두개를 한다 -> 값과 키가 출력되고
    -> 세개를 쓰면 인덱스까지도 출력이 된다.

배열 반복

    <div v-for="(item, index) in myArr">
      {{ index }} // {{item.name}}
    </div>


객체 반복

    <div v-for="(value, key, index) in myObj">
      {{ index }} // {{key}} // {{value}}
    </div>


여러 요소에 대한 v-for 적용

  • template 요소에 v-for를 사용하여 하나 이상의 요소에 대해 반복 렌더링 할 수 있음
  <!-- v-for on <template> -->
    <ul>
      <template v-for="item in myArr">
        <li> {{ item.name }}</li>
        <li> {{item.age}} </li>
        <hr>
      </template>
    </ul>


중첩된 v-for

  • 각 v-for 범위는 상위 범위에 접근 할 수 있음
    <!-- nested v-for -->
    <ul v-for="item in myInfo">
      <li v-for="friend in item.friends">
        {{item.name}} - {{ friend }}
      </li>
    </ul>


v-for with key

반드시 v-for 와 key를 함께 사용한다

  • 내부 컴포넌트의 상태를 일관되게 유지
  • 데이터의 예측 가능한 행동을 유지(Vue 내부 동작 관련)
  • key는 반드시 각 요소에 대한 고유한 값을 나타낼 수 있는 식별자여야 함
  • 키를 각각의 요소에 연결시켜줌

v-for with v-if

> 동일 요소에 함께 사용하지 않는다!!

  • 동일 요소에서 v-if가 v-for보다 우선순위가 더 높기 때문
    -> v-if 조건은 v-for 범위의 변수에 접근할 수 없음

문제상황1

  • todo 데이터 중 이미 처리 한(isComplete === true) todo 만 출력하기
  • 아래와 같이 하면 오류가 난다.
  • 아직 todo가 반복돌면서 나오기 때문에 정의되지 않았다고 함
    <!-- [Bad] v-for with v-if -->
    <ul v-for="todo in todos" v-if="!todo.isComplete" :key="todo.id">
      <li>
        {{todo.name}}
      </li>
    </ul>

해결법
1. computed를 활용해 필터링 된 목록을 반환하여 반복하도록 설정

  const completeTodos = computed(() => {
          return todos.value.filter((todo) => !todo.isComplete)
        })
        
 <li v-for="todo in completeTodos" :key="todo.id">
        {{todo.name}}
      </li>
  1. 템플릿태그를 이용해서 둘의 위치를 따로 분리시키는 방법도 있음

4. Watchers

watch()

  • 반응형 데이터를 감시하고, 감시하는 데이터가 변경되면 콜백 함수를 호출
  • 리턴에는 템플릿에서 쓰일 것들만 넣는다.

구조

variable - 감시하는 변수
newValue - 감시하는 변수가 변화된 값 / 콜백 함수의 첫번째 인자
oldValue - 콜백 함수의 두번째 인자

1. 감시하는 변수에 변화가 생겼을 때 기본 동작 확인하기

const countWatch = watch(count, (newValue, oldValue) => {
	console.log(`newValue: ${newValue}, oldValue: ${oldValue}`)
})

2. 감시하는 변수에 변화가 생겼을 때 연관 데이터 업데이트하기

const messageWatch = watch(message, (newValue, oldValue) => {
    messageLength.value = newValue.length
})


Computed와 Watchers

★ computed와 watch 모두 의존(감시)하는 원본 데이터를 직접 변경하지 않음!!


5. Lifecycle Hooks

  • Vue 인스턴스의 생애주기 동안 특정 시점에 실행되는 함수
  • 개발자가 특정 단계에서 의도하는 로직이 실행될 수 있도록 함
  1. Vue 컴포넌트 인스턴스가 초기 렌더링 및 DOM 요소 생성이 완료된 후 특정 로직을 수행하기

    onMounted = 앱이 템플릿에 마운트되었을때(연결되었을때) 출력됨

 onMounted(() => {
          console.log('mounted')
        })
  1. 반응형 데이터의 변경으로 인해 컴포넌트의 DOM이 업데이트된 후 특정 로직을 수행하기

    onupdated = 업데이트 되엇을 때!!

Lifecycle Hooks 특징

  • Vue 는 Lifecycle Hooks에 등록된 콜백 함수들을 인스턴스와 자동으로 연결
  • 이렇게 동작하려면 hooks 함수들은 반드시 동기적으로 작성되어야 함
  • 인스턴스 생애 주기의 여러 단계에서 호출되는 다른 hooks 도 있으며, 가장 일반적으로 사용되는 것은 onMounted, onUpdated, onUnmounted

6. Vue Style Guide

스타일 가이드

참고

  • computed의 반환 값은 의존하는 데이터의 파생된 값
  • 일종의 snapshot이며 의존하는 데이터가 변경될 때마다 새 snapshot이 생성됨
  • snapshot을 변경하는 것은 의미가 없으므로 계산된 반환 값은 읽기 전용으로 취급되어야 하며 변경되어서는 안됨
  • 대신 새 값을 얻기 위해서는 의존하는 데이터를 업데이트 해야 함
computed에서 reverse() 및 sort() 사용시 원본 배열을 변경하기 때문에 복사본을 만들어서 진행해야 함

배열의 인덱스를 v-for의 key로 사용하지 말 것
  • 인덱스는 식별자가 아닌 배열의 항목 위치만 나타내기 때문에 Vue가 DOM을 변경 할 때 (끝이 아닌 위치에 새 항목이 배열에 삽입되면) 여러 컴포넌트간 데이터 공유 시 문제가 발생
  • 직접 고유한 값을 만들어내는 메서드를 만들거나 외부 라이브러리 등을 활용하는 등 식별자 역할을 할 수 있는 값을 만들어 사용

v-for와 배열-'배열 변경 감지'

  • 수정 메서드 (원본 배열 수정)
    - Vue는 반응형 배열의 변경 메소드가 호출 되는 것을 감지하여, 필요한 업데이트를 발생시킴
    • push(), pop(), shift(). unshift(), splice(), sort(), reverse()
  • 배열 교체
    - 원본 배열을 수정하지 않고 항상 새 배열을 반환
    • filter(), concat(), clice()
profile
나의 행복 만들기

0개의 댓글