혼자 적어보는 노트

프로그래머스 데브코스 TIL - Day 36 본문

스터디

프로그래머스 데브코스 TIL - Day 36

jinist 2022. 5. 11. 01:04

✅ 오늘의 학습

📌 Vue (3)

 

- 조건부 렌더링

- 리스트 렌더링

- 이벤트 핸들링

- 폼 입력 바인딩

 


 

조건부 렌더링

 

v-if / v-else-if / v-else

조건에 맞는 값에 따라 출력되는 결과를 정할 수 있다.

<div id="app">
  <h1 v-if="null">if</h1>
  <h1 v-else-if="0">else-if</h1>
  <h1 v-else>else!!</h1>
</div>

 

template

template 태그를 사용하면 조건 만족 시 template 내부의 엘리먼트들만 출력된다.

<div id="app">
  <template v-if="true">
    <h1>안녕하세요</h1>
  </template>
</div>

 

💡 v-show와 v-if 차이

 

v-if

데이터가 falsy값일 경우 해당 엘리먼트의 렌더링 자체를 하지 않고 <--v-if-->라는 주석이 생긴다.
* 초기 렌더링 비용이 낮지만 전환 비용이 높다.

 

v-show

데이터가 falsy값일 경우 해당 엘리먼트는 존재하지만 스타일 속성인 display가 none이 된다.

* 초기 렌더링 비용이 높지만 전환 비용이 낮다.

* 컴포넌트의 데이터 연결 전 이중 중괄호 구문이 잠시 보일 수 있기 때문에

  v-cloak과 함께 사용하는 것이 좋다.

 

v-cloak

컴포넌트 인스턴스가 컴파일을 완료할 때까지 남아있고 준비가 끝나면 해당 속성을 제거한다.
* 컴파일 되지 않은 이중 중괄호 구문을 숨기는 데 사용할 수 있다.

* 속성 선택자를 전역으로 선언해서 사용할 수 있다.

<style>
  [v-cloak] {
    display: none;
  }
</style>

<div id="app">
  <h1 v-show="isShow" v-cloak>{{ msg }}</h1>
</div>

 

 

v-for, v-if 분리해서 사용하기

공식 문서의 스타일 가이드에 따르면 v-for를 쓴 엘리먼트에 v-if를 함께 사용하면 안 된다.

template을 사용하여 동시 사용을 피할 수 있다.

<ul>
  <template v-for="user in users" :key="user.id">
    <li v-if="user.isActive">
      {{ user.name }}
    </li>
  </template>
</ul>

 

 

v-for을 사용한 객체 속성 반복

* 순서는 Object.keys()의 키 나열 순서에 따라 결정되며

Javascript엔진에 따라 순서가 일관적이지 않을 수 있다.

<li v-for="value in myObject">
  {{ value }}
</li>


<!-- value, key, index를 인자로 받아서 사용할 수 있다. -->

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

 

 

 

💡

Vue에서는 기존의 배열을 교체하더라도 새롭게 전부 렌더링 하는 것이 아니라

변경된 부분만 체크해서 변경을 한다. 이 부분은 리액트와 비슷한 개념인 듯하다.

 

 

 

간단한 TodoList 예제 만들기

<div id="app">
  <form @submit.prevent="addTodo">
    <label for="new-todo">오늘의 할 일:</label>
    <input id="new-todo" v-model="todoText" />
    <button>추가</button>
  </form>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      {{todo.title}}
      <button @click="removeTodo(todo.id)">삭제</button>
    </li>
  </ul>
</div>
<script>
  function generateId() {
    return `${Date.now()}${Math.random()}`;
  }
  const App = {
    data() {
      return {
        todoText: "",
        todos: [],
      };
    },
    methods: {
      addTodo(event) {
        this.todos.push({
          id: generateId(),
          title: this.todoText,
        });

        this.todoText = "";
      },
      removeTodo(todoId) {
        this.todos = this.todos.filter((todo) => todo.id !== todoId);
      },
    },
  };
  const vm = Vue.createApp(App).mount("#app");
</script>

 

Todo List 컴포넌트화 시키기

<ul>
  <todo-item v-for="todo in todos"
              :key="todo.id"
              :todo="todo"
              @remove="removeTodo" />
</ul>
const TodoItem = {
    template: `
    <li>
      {{todo.title}}
      <button @click="$emit('remove', todo.id)">삭제</button>
    </li>
    `,
    props: ["todo"],
  };

❗❗ 여기서 중요한 부분!

 

1. props로 받을 데이터를 :todo를 사용해서 받기

2. 내부의 이벤트 처리는 내부 엘리먼트에서 $emit으로 커스텀 이벤트를 생성하여 이벤트 발생 시

컴포넌트에서 받아서 처리를 한다.

$emit에서는 인자를 전달하지만 @remove로 실행 시는 removeTodo는 인자가 없다.

 

이 부분은 몇 번 더 커스텀 이벤트를 생성해 보고 다뤄봐야 익숙해질 듯하다.

 

 

이벤트 핸들링

지정한 인자와 함께 event객체를 사용하려면 $event를 사용하여 전달한다.

<button @click="hello('안녕')">클릭</button>

<button @click="hello('안녕', $event)">클릭</button>
hello(message, event) {
    console.log(message);
    console.log(event);
  },

 

함수 동시 실행

<button @click="a(); b(); c()">클릭</button>
<button @click="a(), b(), c()">클릭</button> <!-- Vue3 부터 제공 -->

 

 

이벤트 수식어

 

Vue에서는 이벤트 핸들러 내부의 데이터 로직에서 사용할 수 있는 메서드들을 제공한다.

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

* 수식어는 체이닝이 가능하다

 

 

 

passive

화면 렌더링과 동작의 처리를 부드럽게 해주는 이벤트 수식어.

 

+ passive속성을 처음 알게 되면서 찾아보게 된 EventListener의 옵션이다.

document.addEventListener("touchstart", handler, {
  capture: false,
  once: false,
  passive: false
});

capture: 이벤트 캡쳐링 적용 여부
once: 이벤트를 한 번만 호출하고 해제되는 옵션
passive: 스크롤 성능 향상을 위한 옵션으로 true일 경우, 스크롤을 위해 블록 되는 것을 방지

 

 

💡 passive에 대한 설명


브라우저에서는 터치 혹은 휠 이벤트가 발생할 때마다
스크롤을 할지 말지 결정을 해야 하는데
스크롤이 발생하면 많은 이벤트가 발생하게 되고,
이벤트마다 스크롤을 할지 말지 판단하게 된다면 브라우저가 느려질 수 있다.

 

이때 passive 속성을 사용해서 브라우저에게 preventDefault를 사용해서
스크롤을 막지 않겠다고 알려주어 결정하는데 낭비되는 자원을 절약하는 방식이다.

 

 

이외의 이벤트 수식어의 자세한 내용들은 공식 문서에서 확인할 수 있다.

공식 문서: 이벤트 수식어

 

 

키 수식어

@keyup.enter와 같이 keyboardEvent.key를 통한 유효 키 이름을 케밥케이스로 변환하여
수식어로 사용할 수 있다.

 

*체이닝을 사용하여 동시입력 또한 지원이 된다.

@keydown.arrow-down

 

* meta key는 keyup에서 동작하지 않기 때문에 keydown에서 사용해야 한다.

* 다른 키와 조합해서 사용하고 싶지 않다면 exact를 사용한다.

@keydown.arrow-down.exact
@click.exact

 

마우스 버튼 수식어

마우스의 왼쪽, 오른쪽 버튼을 감지할 수 있다.

@click.left
@click.right

 

 

폼 입력 바인딩

공식 문서: 폼 입력 바인딩

 

 

v-model의 경우 아래와 같은 두 개의 속성을 단축시킨 것과 같다.

:value="msg"
@input="msg = $event.target.value"

❗❗ v-model을 사용하여 input을 다룰 때 한글을 입력할 경우 실시간 반영이 되지 않고

하나의 글자를 완성을 해야 반영이 되기 때문에 이벤트 핸들러를 직접 작성하여 사용하는 것을 권장한다.

 

checkbox

v-model을 통해 checkbox에서 일반적인 boolean데이터가 아닌

배열 데이터를 연결할 경우, 체크 여부에 따라 value의 값이 객체 형태로 담기게 된다.

<div id="app">
  <input type="checkbox" v-model="checked" value="1번" />
  <input type="checkbox" v-model="checked" value="2번" />
  <input type="checkbox" v-model="checked" value="3번" />
</div>
const vm = Vue.createApp({
    data() {
      return {
        checked: [], // {0: '1번', 1: '2번', 2: '3번'}
      };
    },
}).mount("#app");

 

 

select

v-model을 사용하여 선택한 옵션의 value를 데이터에 담을 수 있다.

<div id="app">
  <select v-model="selected">
    <option value="">과일을 선택해주세요.</option>
    <option v-for="fruit in fruits"
            :value="fruit.value"
            :key="fruit.value">{{ fruit.text }}</option>
  </select>
</div>
<script>
  const vm = Vue.createApp({
    data() {
      return {
        selected: "",
        fruits: [
          { value: "사과", text: "apple" },
          { value: "오렌지", text: "orange" },
          { value: "바나나", text: "banana" },
        ],
      };
    },
  }).mount("#app");
</script>

*value와 표시할 text가 같다면 value를 생략하고 표현할 수 있다.

 

 

v-model의 수식어

 

.lazy

해당 수식어를 추가하면 change이벤트 이후에 동기화할 수 있다.
input이벤트로 동작하는 양방향 데이터 바인딩을 change로 변환을 시켜주는 기능이라고 볼 수 있다.

 

.number
사용자 입력이 숫자일 경우, 자동으로 숫자로 형 변환되기를 원할 때 사용할 수 있다.

 

.trim
사용자의 입력한 내용의 앞뒤 공백을 제거해주는 기능이다.

 


✍ 느낀 점

view model이 파기되면 이벤트 리스너가 제거되기 때문에

수동으로 해지하지 않아도 된다는 점이 인상 깊었다.

또한, 개발자의 입장에서 자잘하고 반복적으로 처리를 해주어야 하는 부분들을

간단한 키워드 하나로 처리를 해줄 수 있다는 부분이 정말 편하다고 느꼈다.

사용을 해보기 전엔 크게 느끼진 못했지만.. 알면 알 수록 왜 편하다고 하는지 알 듯하다.

Comments