데브코스 프론트엔드 5기/Vue

231122 [Day 47] Vue(3)

코딩하는 키티 2023. 11. 23. 21:41

조건부 렌더링

v-if

v-if 디렉티브는 조건부로 블록을 렌더링하는 데 사용된다.

블록은 디렉티브 표현식이 truthy 값을 반환하는 경우에만 렌더링

 

v-else

v-else 디렉티브를 사용하여 v-if에 대한 "else 블록"을 나타낼 수 있다.

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  A/B/C 아님
</div>

 

 

v-if는 디렉티브이므로 단일 엘리먼트에 연결해야 한다.

하지만 둘 이상의 엘리먼트를 전환하려면 <template> 엘리먼트에 v-if를 사용할 수 있다.

<template v-if="ok">
  <h1>제목</h1>
  <p>단락 1</p>
  <p>단락 2</p>
</template>

 

 

v-show

v-show가 있는 엘리먼트는 항상 렌더링되고 DOM에 남아 있다. 엘리먼트의 display CSS 속성만 전환.

v-cloak을 같이 사용하는게 좋다. + 속성 선택자를 전역으로 등록시킨다.

(v-cloak: 준비될 때까지 컴파일되지 않은 템플릿을 숨기는 데 사용, [v-cloak] { display: none }과 같은 CSS 규칙과 결합하여, 컴포넌트가 준비될 때까지 템플릿을 숨기는 데 사용

 

 

차이점

v-if는 조건이 true인 경우에는 해당요소를 실제로 구조화해서 출력, false인 경우에는 아예 구조적으로 만들지 않는다.

또한 v-if는 게으르므로(lazy), 초기 조건이 false면 아무 작업도 수행하지 않는다. 조건부 블록은 조건이 true가 될 때까지 렌더링되지 않는다.

 

v-show는 데이터의 참,거짓과 상관 없이 해당요소를 구조적으로 출력한다. CSS 기반으로 전환 되므로, 초기 조건과 관계없이 항상 렌더링 된다.

 

v-if는 전환 비용이 더 높고, v-show는 초기 렌더링 비용이 더 높다. 따라서 매우 자주 전환해야 하는 경우 v-show를, 실행 중에 조건이 변경되지 않는 경우 v-if를 사용하는 것이 좋다.

 

 

리스트 렌더링

v-for

  • v-for 디렉티브를 사용하여 배열을 리스트로 렌더링할 수 있다.
  • item in items 형식의 문법이 필요하다. 여기서 items는 배열이고, item은 배열 내 반복되는 앨리먼트의 **별칭(alias)**

배열 변경 감지

Vue는 반응형 배열의 변경 메소드가 호출 되는것을 감지

- 수정 메서드 : push(), pop(), shift(), unshift(), splice(), sort(), reverse()

 

- 배열 교체

수정 메서드는 이름에서 알 수 있듯이 호출된 원래 배열을 수정한다.

이에 비해 수정이 아닌 방법도 있다. filter(), concat()  slice()는 원본 배열을 수정하지 않고 항상 새 배열을 반환한다.

// `items`는 값이 있는 배열의 ref라고 가정된 경우입니다.
items.value = items.value.filter((item) => item.message.match(/Foo/))

 

- 필터링/정렬 결과 표시

필터링되거나 정렬된 배열을 반환하는 계산된 속성을 만들 수 있다.

 

- v-if와 유사하게 <template> 태그에 v-for를 사용하여 여러 엘리먼트 블록을 렌더링할 수 있다.

- 컴포넌트에 v-for를 직접 사용할 수 있다. (key 사용)

 

 

이벤트 핸들링

이벤트 리스닝하기

  • v-on 디렉티브는 단축 문법으로 @ 기호를 사용
  • DOM 이벤트를 수신하고 트리거될 때, 사전 정의해둔 JavaScript 코드를 실행할 수 있다.
  •  v-on:click="handler" 또는 @click="handler"

핸들러 값

  1. 인라인 핸들러: 이벤트가 트리거될 때 실행되는 인라인 JavaScript(네이티브 onclick 속성과 유사).
  2. 메서드 핸들러: 컴포넌트에 정의된 메서드 이름 또는 메서드를 가리키는 경로.

 

메서드 핸들러

대부분의 이벤트 핸들러 논리는 복잡, 인라인 핸들러에서는 실현 가능하지 않을 수 있다.

=> v-on은 컴포넌트의 메서드 이름이나 메서드를 가리키는 경로를 실행할 수 있게 구현

 

 

인라인 핸들러에서 메서드 호출

메서드 이름을 직접 바인딩하는 대신, 인라인 핸들러에서 메서드를 호출할 수 있다.

 

인라인 핸들러에서 이벤트 객체 접근

 인라인 핸들러에서 네이티브 DOM 이벤트 객체에 접근해야 하는 경우도 있다. 특수한 키워드인 $event를 사용하여 메서드에 전달

<!-- 특수한 키워드인 $event 사용 -->
<button @click="warn('아직 양식을 제출할 수 없습니다.', $event)">
  제출하기
</button>

<!-- 인라인 화살표 함수 사용 -->
<button @click="(event) => warn('아직 양식을 제출할 수 없습니다.', event)">
  제출하기
</button>

//js
function warn(message, event) {
  // 이제 네이티브 이벤트 객체에 접근할 수 있습니다.
  if (event) {
    event.preventDefault()
  }
  alert(message)
}

 

 

이벤트 수식어

.stop / .prevent / .self / .capture / .once / .passive

<!-- 클릭 이벤트 전파가 중지됩니다. -->
<a @click.stop="doThis"></a>

<!-- submit 이벤트가 더 이상 페이지 리로드하지 않습니다. -->
<form @submit.prevent="onSubmit"></form>

<!-- 수식어를 연결할 수 있습니다. -->
<a @click.stop.prevent="doThat"></a>

<!-- 이벤트에 핸들러 없이 수식어만 사용할 수 있습니다. -->
<form @submit.prevent></form>

<!-- event.target이 엘리먼트 자신일 경우에만 핸들러가 실행됩니다. -->
<!-- 예를 들어 자식 엘리먼트에서 클릭 액션이 있으면 핸들러가 실행되지 않습니다. -->
<div @click.self="doThat">...</div>

<!-- 이벤트 리스너를 추가할 때 캡처 모드 사용 -->
<!-- 내부 엘리먼트에서 클릭 이벤트 핸들러가 실행되기 전에, 여기에서 먼저 핸들러가 실행됩니다. -->
<div @click.capture="doThis">...</div>

<!-- 클릭 이벤트는 단 한 번만 실행됩니다. -->
<a @click.once="doThis"></a>

<!-- 핸들러 내 `event.preventDefault()`가 포함되었더라도 -->
<!-- 스크롤 이벤트의 기본 동작(스크롤)이 발생합니다.        -->
<div @scroll.passive="onScroll">...</div>

 

이 코드처럼 간단하게 표현 가능

 

- passive : 화면의 렌더링과 로직의 동작을 분리해서 처리 => 쾌적한 환경 제공

 

 

입력키 수식어

키보드 이벤트를 수신할 때, 특정 키를 확인해야 하는 경우가 많기 때문에, 키 수식어를 지원

<!-- `key`가 `Enter`일 때만 `submit`을 호출합니다 -->
<input @keyup.enter="submit" />

 

KeyboardEvent.key를 통해 유효한 입력키 이름을 kebab-case로 변환하여 수식어로 사용

<input @keyup.page-down="onPageDown" />

위의 예에서 핸들러는 $event.key가 'PageDown'일 경우에만 호출

 

 

입력키 별칭

Vue는 가장 일반적으로 사용되는 키에 대한 별칭을 제공

.enter / .tab / .delete ("Delete" 및 "Backspace" 키 모두 캡처) / .esc / .space / .up / .down / .left / .right

 

시스템 입력키 수식어

마우스 또는 키보드 이벤트 리스너는 아래 수식어를 사용하여, 해당 입력키를 누를 때만 트리거 되도록 할 수 있다.

.ctrl  / .alt / .shift / .meta

 

마우스 버튼 수식어

.left / .right / .middle

 

 

 

왜 html로 된 리스너를 사용하는가?

  1. html 템플릿을 간단히 해서 js 코드 내에서 핸들러 함수 구현을 찾는 것이 더 쉽다.
  2. js에서 이벤트 리스너를 수동으로 연결할 필요가 없으므로 뷰모델 코드는 순수 로직과 DOM이 필요하지 않다. 테스트가 쉬워짐.
  3. 뷰모델이 파기되면 모든 이벤트 리스너가 자동으로 제거 된다. 이벤트 제거에 대한 걱정이 필요없어짐.

 

폼 입력 바인딩

프론트엔드에서 폼을 처리할 때, 폼 입력 엘리먼트의 상태를 JavaScript의 상태와 동기화해야 하는 경우가 많다.

<input
  :value="text"
  @input="event => text = event.target.value">
  
  // 아래처럼 바꿀 수 있다.
  <input v-model="text">

 

  • 텍스트 유형의 <input>과 <textarea> 경우, value 속성과 input 이벤트를 사용한다.
  • <input type="checkbox">과 <input type="radio"> 경우, checked 속성과 change 이벤트를 사용한다.
  • <select>는 value를 속성으로 사용하고 change를 이벤트로 사용한다.

 

사용법

 

텍스트

<p>메세지: {{ message }}</p>
<input v-model="message" placeholder="메세지 입력하기" />

 

한국어는 v-model이 업데이트되지 않는다.  대신 직접 구현한 input 이벤트 리스너와 value 바인딩을 사용해 기능을 구성해야 한다.

 

 

여러 줄 텍스트

<span>여러 줄 메세지:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="여러 줄을 추가해보세요"></textarea>

 

<textarea> 내부에 이중 중괄호 문법은 작동하지 않으므로 v-model을 사용

<!-- 잘못된 사례 -->
<textarea>{{ text }}</textarea>

<!-- 올바른 사례 -->
<textarea v-model="text"></textarea>

 

 

체크박스

단일 체크박스는 불리언을 값을 사용

<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

 

배열 또는 Set에 여러 개의 체크박스 값을 바인딩할 수도 있다.

const checkedNames = ref([])
<div>체크된 이름: {{ checkedNames }}</div>

<input type="checkbox" id="jack" value="젝" v-model="checkedNames">
<label for="jack">젝</label>

<input type="checkbox" id="john" value="존" v-model="checkedNames">
<label for="john">존</label>

<input type="checkbox" id="mike" value="마이크" v-model="checkedNames">
<label for="mike">마이크</label>

 

 

라디오

<div>선택한 것: {{ picked }}</div>

<input type="radio" id="one" value="하나" v-model="picked" />
<label for="one">하나</label>

<input type="radio" id="two" value="둘" v-model="picked" />
<label for="two">둘</label>

 

셀렉트

단일 셀렉트

<div>선택됨: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">다음 중 하나를 선택하세요</option>
  <option>가</option>
  <option>나</option>
  <option>다</option>
</select>

 

다중 선택(배열로 바인딩 됨)

<div>선택됨: {{ selected }}</div>

<select v-model="selected" multiple>
  <option>가</option>
  <option>나</option>
  <option>다</option>
</select>

 

 

수식어

.lazy

기본적으로 v-model은 각 input 이벤트 이후 데이터와 입력을 동기화한다.

대신 change 이벤트 이후에 동기화하기 위해 .lazy 수식어를 추가할 수 있다.

<!-- "input" 대신 "change" 이벤트 후에 동기화됨 -->
<input v-model.lazy="msg" />

 

.number

사용자 입력이 자동으로 숫자로 유형 변환되도록 하려면, v-model 수식어로 .number를 추가

<input v-model.number="age" />

 

값을 parseFloat()로 파싱할 수 없으면 원래 값이 대신 사용된다.

인풋에 type="number"가 있으면 .number 수식어가 자동으로 적용된다.

 

.trim

사용자 입력의 공백이 자동으로 트리밍되도록 하려면 v-model 수식어로 .trim을 추가하면 된다

<input v-model.trim="msg" />

'데브코스 프론트엔드 5기 > Vue' 카테고리의 다른 글

231120 [Day 45] Vue (1)  (2) 2023.11.21