BeNI 2022. 12. 12. 01:30
728x90

 

1. 조건부 렌더링

 

1) v-if, v-else-if, v-else

: 해당 블록을 조건부로 렌더링하는 데 사용

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

- v-else는 v-else-if나 v-if 다음 블록에 와야 인식이 된다. 

 

✅ template

- template는 요소들을 래핑해주는 역할로 template 자체는 dom에 보이지 않는다.

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

- v-if가 ok면 내부 요소만 렌더링 된다. 

 

 

2) v-show

- 요소를 조건부로 표시하는 다른 옵션

<h1 v-show="ok">Hello!</h1>

 

📌 v-show와 v-if 비교

v-show는 요소가 항상 렌더링 되고, dom에 남아있다. 👉 초기렌더링 비용 ↑, 화면 전환 비용 ↓

v-if 문은 조건이 만족하지 않을 경우 요소가 렌더링 되지 않는다. 👉 초기렌더링 비용 ↓ , 화면 전환 비용 ↑ (lazy하다)

* v-show는 v-cloak 옵션과 같이 사용하는 것이 좋다.(예시) 초기 렌더링 시 숨겨야 할 때

v-cloak : 연결된 컴포넌트 인스턴스가 컴파일을 완료할 때 까지 요소에 남아있다.

<style>
  [v-cloak] {
    display: none;
  }
</style>
<div id="app">
  <h1 v-show="isShow" v-cloak>Hello Vue!</h1>
</div>

 

✅ v-if와 v-for 함 사용하기

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

- li에 v-for을 작성하지 않고 template를 이용하여 요소가 생성되는 걸 막는다.

* v-if가 v-for보다 우선순위가 높기 때문에 for의 값을 참조할 때 오류가 생김(computed로 해결은 가능)

 

 

2. 리스트 렌더링

1) v-for 

: 배열을 기반으로 항목 목록을 렌더링 할 수 있다.

data() {
  return {
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
<li v-for="item in items">
  {{ item.message }}
</li>

* 두번 째 인자를 넣어 인덱스도 참조 가능하다. (item, idx)

 

✅ 객체

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

 

✅ 숫자 

<span v-for="n in 10">{{ n }}</span>

- 1부터 시작함

 

* key : v-for을 이용해 요소를 여러개 렌더링 할 때는 고유 속성을 부여하는 것이 권장된다.

<template v-for="todo in todos" :key="todo.name">
  <li>{{ todo.name }}</li>
</template>

 

* 배열을 새로운 배열로 할당할 때(filter 이용) vue가 최적화 하기 때문에 효율적임

 

 

ex) todoList 추가, 삭제 

<body>
<div id="app">
  <form @submit="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="now-todo"
      type="text"
      placeholder="E.g. Feedt the cat"
    />
    <button>Add</button>
  </form>
  <ul>
    <todo-item
      v-for="todo in todos"
      :key="todo.id"
      :todo="todo"
      @remove="removeTodo"
    />
  </ul>
</div>
<script>
  // 단방향이다 :value
  function generateId() {
    return `${Date.now()}${Math.random()}`;
  }
  const TodoItem = {
    template: ` <li>
      {{todo.title}}
      <button @click="$emit('remove', todo.id)">Remove</button>
    </li>`,
    props: ["todo"],
  };
  const App = {
    components: {
      TodoItem,
    },
    data() {
      return {
        newTodoText: "",
        todos: [],
      };
    },
    methods: {
      addNewTodo(e) {
        e.preventDefault();
        this.todos.push({
          id: generateId(),
          title: this.newTodoText,
        });
        this.newTodoText = "";
        console.log(this.todos);
      },
      removeTodo(todoId) {
        this.todos = this.todos.filter((todo) => todo.id !== todoId);
      },
    },
  };
  const vm = Vue.createApp(App).mount("#app");
</script>
</body>

 

 

 

2. 이벤트 핸들링

1) v-on(@)

: DOM 이벤트를 수신하고 트리거할 수 있음

<button @click="greet">Greet</button>

- 버튼 클릭시, methods 내부에 정의한 greet() 를 실행한다.

 

* 함수 매개변수 : 순서와 상관없이 $event 가 이벤트를 가져온다.

$을 안붙이면 마지막 매개변수가 event가 된다.

<button @click="say('hello', $event)">Say hello</button>

 

✅ 여러 함수 할당 : 순서대로 실행된다.

<h1 @click="a(); b(); c();">{{msg}}</h1>

 

2) 이벤트 수식어

  • .stop : event.stopPropagation()
  • .prevent : event.preventDefault()
  • .self : event.currentTarget(이벤트가 등록된 대상) = event.target(이벤트가 실행된 요소) 일 때
  • .capture : 상위 요소부터 이벤트가 내려옴
  • .once : 한번만 실행
  • .passive : log 랑 화면 렌더링 분리함
<a @click.stop.once="doThis"></a>

 

3) 키 이벤트

<input @keyup.enter="submit" />
<input type="text" @keyup.alt.exact="log" /> alt만 누를때

- enter를 입력했을 때 submit 실행

- exact를 이용하면 그 키만 눌렀을 때 실행하도록 할 수 있다.

 

4) 마우스 이벤트

  • .left
  • .right
  • .middle

⚠️ 뷰에서는 이벤트를 바인딩한 요소가 삭제되면 이벤트 리스너도 같이 삭제된다

 

 

 

3. 폼 입력 바인딩

1) :value : 단방향 데이터 바인딩

<h1>{{msg}}</h1>
<input type="text" :value="msg" @input="msg=$event.target.value"/>

- input에 입력한 텍스트를 h1요소와 동기화 하기 위해선(양방향) input 이벤트를 이용해야 한다.

 

2) v-model : 양방향 데이터 바인딩

<h1>{{msg}}</h1>
<input type="text" v-model="msg" />

 

✅ checkbox

<input type="checkbox" v-model="checked" />
<input type="checkbox" v-model="checked" checked />

- checked 옵션을 주면 기본으로 체크되어 있다.

- v-model 값을 배열로 설정해 놓으면 checked 된 value값들이 배열로 들어 간다.

 

✅ radio

  <input v-model="picked" type="radio" value="Leon" />
  <input v-model="picked" type="radio" value="euna" />
  <input v-model="picked" type="radio" value="able" />
data() {
  return {
    picked: "",
  };
},
watch: {
  picked(newValue) {
    console.log(newValue);
  },
},

 

✅ select

<div>Selected: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Please select one</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

 

 

3) 수식어

ⓐ .lazy : 이벤트 후에 값을 동기화

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

 

ⓑ .number : 사용자 입력이 자동으로 숫자로 변경

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

ⓒ .trim : 공백 제거

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

 

 

4. 컴포넌트 기초

1) props 사용

const app = Vue.createApp(App);
  app.component("upper-name", {
    template: `<div>{{name}}</div>`,
    props: ["name"],
    },
 });
<upper-name name="apple"></upper-name>
<upper-name name="banana"></upper-name>
<upper-name name="cake"></upper-name>

 

2) 하위 컴포넌트에서 상위 컴포넌트 data 수정

- emit을 이용한다.

 <upper-name
    v-for="fruit in fruits"
    :key="fruit.id"
    :name="fruit.name"
    @to-upper="toUpper(fruit, $event)"
></upper-name>
const app = Vue.createApp(App);
  app.component("upper-name", {
    template: `<div @click="capitalize">{{name}}</div>`,
    props: ["name"],
    methods: {
      capitalize() {
        this.$emit("to-upper", this.name.toUpperCase());
      },
    },
 });

- emit의 첫번째 인자는 커스텀 이벤트 이름이다.

methods: {
  toUpper(fruit, uppername) {
    fruit.name = uppername;
  },
},

upper-name 클릭시 capitalize를 실행하고,

upper-name 컴포넌트에서 to-upper라는 이벤트를 바인딩하여 toUpperCase()한 걸 

상위 컴포넌트의 methods인 toUpper를 실행하여 값이 바뀌게 된다.

 

 

 

728x90