속성 바인딩)

 

HTML 속성을 동적 값에 바인딩 하려면 v-bind 디렉티브를 사용한다.

<div v-bind:id="dynamicId"></div>

 

 

엘리먼트의 id 속성은 컴포넌트 상태의 dynamicId 속성과 동기화 된다.

 

v-bind는 다음과 같이 생략이 가능하다.

<div :id="dynamicId"></div>

 

만약 다음과 같이 여러 속성을 나타내는 Javascript 객체가 있는 경우

data() {
  return {
    objectOfAttrs: {
      id: 'container',
      class: 'wrapper'
    }
  }
}

특별한 인자 없이 v-bind를 사용하여 단일 엘리먼트에 속성을 바인딩 할 수 있다.

<div v-bind="objectOfAttrs"></div>

다음과 같이 id와 class가 바인딩 된다.

 

 

 

이벤트 리스너)

 

v-on 디렉티브를 사용하여 DOM 이벤트를 수신할 수 있다.

<button v-on:click="increment">{{ count }}</button>

여기서 click의 인자는 수신할 이벤트의 이름이다.

 

v-on은 다음과 같이 단축 문법으로 사용 가능하다.

<button @click="increment">{{ count }}</button>

 

 

폼(form) 바인딩)

v-bind와 v-on을 함께 사용하면, form 안의 입력 엘리먼트에 양방향 데이터 바인딩을 만들 수 있다.

<input :value="text" @input="onInput">
<p>{{ text }}</p>
methods: {
  onInput(e) {
    // v-on 핸들러는 네이티브 DOM 이벤트를 인자로 받습니다.
    this.text = e.target.value
  }
}

입력란에 값을 입력하면 p 태그의 텍스트가 실시간으로 업데이트 된다.

 

 

Vue는 양방향 바인딩을 단순화하기 위해, 위 문법을 간편 표기하는 v-model 디렉티브를 제공한다.

<input v-model="text">

즉 v-model은 v-bind와 v-on을 합쳐놓은 것이라고 생각하면 된다.

v-model은 텍스트 입력 외에도 체크박스, 라디오 버튼, 셀렉트 드롭다운과 같은 다른 입력 타입에서도 사용할 수 있다.

(form 안의 요소에서 v-model을 사용한다고 생각하면 된다)

 

 

조건부 렌더링)

엘리먼트를 조건부로 렌더링하기 위해 v-if 디렉티브를 사용할 수 있다.

<h1 v-if="awesome">Vue는 굉장해! 엄청나!</h1>

awesome 값이 truthy인 경우에만 렌더링 된다.awesome 값이 falthy 값으로 변경되면 DOM에서 아예 제거된다. (태그 자체가 사라짐)

 

v-else나 v-else-if를 사용하여 조건에 따라 다르게 렌더링을 할 수 있다.

<h1 v-if="awesome">Vue는 굉장해! 엄청나!</h1>
<h1 v-else>오 안돼 😢</h1>

v-else 엘리먼트는 v-if 또는 v-else-if 엘리먼트 바로 다음에 와야 인식 됨.

v-else  v-else-if Rapper 역할을 하는 <template>에서도 사용할 수 있다.

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

 

 

v-if와 유사한 기능을 하는 옵션으로 v-show가 있다.

<h1 v-show="ok">안녕!</h1>

v-show는 무조건 렌더링은 한다. 하지만 display 속성만 전환할 뿐이다.

v-show는 v-else와 상호작용하지 않음.

 

 

리스트 렌더링)

v-for 디렉티브를 사용하여 자료 배열을 엘리먼트 목록으로 렌더링할 수 있다.

<ul>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
  </li>
</ul>

todo는 현재 배열 엘리먼트에서 반복되는 지역 변수이다. 

v-for 엘리먼트 또는 그 내부에서만 todo에 접근할 수 있다.

여기서는 todos라는 자료 배열의 요소를 하나를 꺼내서 todo라는 지역 변수에 담았고

todo의 id를 key로 사용하고 text를 출력했다.

 

각 todo 객체가 가지고 있는 id 값을 특별한 속성인 key에 바인딩했다.

key는 요소를 구별할 수 있는 unique한 내용을 사용해야 하며, key로 각 요소들을 구분할 수 있게 된다.

 

 

계산된 속성)

computed 옵션을 사용하여 반응적으로 계산되는 속성을 선언할 수 있다.

 

<script>
let id = 0

export default {
  data() {
    return {
      newTodo: '',
      hideCompleted: false,
      todos: [
        { id: id++, text: 'HTML 배우기', done: true },
        { id: id++, text: 'JavaScript 배우기', done: true },
        { id: id++, text: 'Vue 배우기', done: false }
      ]
    }
  },
  computed: {
    filteredTodos() {
      return this.hideCompleted
        ? this.todos.filter((t) => !t.done)
        : this.todos
    }
  },
  methods: {
    addTodo() {
      this.todos.push({ id: id++, text: this.newTodo, done: false })
      this.newTodo = ''
    },
    removeTodo(todo) {
      this.todos = this.todos.filter((t) => t !== todo)
    }
  }
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo" />
    <button>할 일 추가</button>
  </form>
  <ul>
    <li v-for="todo in filteredTodos" :key="todo.id">
      <input type="checkbox" v-model="todo.done">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
  <button @click="hideCompleted = !hideCompleted">
    {{ hideCompleted ? '모두 보이기' : '완료된 항목 숨기기' }}
  </button>
</template>

<style>
.done {
  text-decoration: line-through;
}
</style>

computed 옵션에서,

filteredTodos() 메서드를 사용해서 반응적으로 계산되는 값을 return 할 수 있다.

 

v-for에서 filteredTodos의 결과값이 유동적으로 변하게 되고

따라서 렌더링 되는 list도 버튼을 클릭할 때마다 변하게 된다.

 

 

수명주기와 템플릿 참조)

DOM을 수동으로 작업해야 하는 경우, 특별한 속성인 ref를 사용하여 템플릿 참조를 할 수 있다.

<p ref="p">안녕</p>

하지만 컴포넌트가 마운트된 이후에만 ref를 통해 접근할 수 있다.

마운트 된 후에 실행될 코드는 mounted 옵션을 사용하면 된다.

export default {
  mounted() {
    this.$refs.p.textContent = 'Hello Vue.js!';
  }
}

this.$refs.p 를 통해 p 태그에 접근하고, DOM을 조작하였다.

 

이와 같이 컴포넌트의 수명 주기의 특정 시간에 호출될 콜백을 등록할 수 있다.

 

수명주기에 관한 표는 다음을 참고한다.

 

감시자)

속성에 변화가 생겼을 때 watch 옵션을 사용해서 변경 사항을 감시하고 원하는 사이드 이펙트를 수행할 수 있다.

export default {
  data() {
    return {
      count: 0
    }
  },
  watch: {
    count(newCount, oldCount) {
      // 예, console.log()는 사이드 이펙트입니다.
      console.log(`새로 센 숫자 값은: ${newCount}`)
      console.log(`기존의 숫자 값은: ${oldCount}`)
    }
  }
}

watch에서 사용된 메서드(이름은 변화된 속성값으로 한다)의 첫 번째 인자는 새 값, 두 번째 인자는 기존 값이다.

 

 

컴포넌트)

상위 컴포넌트는 다른 컴포넌트를 템플릿의 하위 컴포넌트로 렌더링할 수 있다.

자식 컴포넌트를 사용하려면 먼저 import를 해서 가져오고, 상위 컴포넌트에서 등록을 해야 한다.

그리고 등록한 컴포넌트의 이름으로 템플릿에서 사용할 수 있다.

<script>
import ChildComp from './ChildComp.vue'
export default {
  components: {
  		ChildComp
	}
}
</script>

<template>
  <!-- 자식 컴포넌트 렌더링 -->
  <ChildComp/>
</template>

 

Props)

자식 컴포넌트는 props를 통해 부모로부터 데이터를 받을 수 있다.

우선, 허용할 props를 선언해야 한다.

// ChildComp.vue
<script>
export default {
  props: {
    msg: String
  }
}
</script>

<template>
  <h2>{{ msg || 'prop이 아직 전달되지 않았습니다!' }}</h2>
</template>

그리고 부모 컴포넌트에서 v-bind를 이용해 greeting 이라는 데이터를 자식 컴포넌트에 msg라는 prop으로 전달한다.

<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      greeting: '부모 컴포넌트로부터 💌을 전달받았어요!'
    }
  }
}
</script>

<template>
  <ChildComp v-bind:msg="greeting"/>
</template>

 

Emits)

자식 컴포넌트는 부모로부터 props를 받는 것 뿐만 아니라 이벤트를 emit(발송)할 수도 있다.

// ChildComp.vue
export default {
  // emit할 이벤트 선언
  emits: ['response'],
  created() {
    // 인자와 함께 emit
    this.$emit('response', '자식 컴포넌트로부터 🌷를 받았어요!')
  }
}

자식 컴포넌트에 이벤트를 선언하고,

this.$emit(첫 번째 인자, 두 번째 인자(선택),...) 으로 이벤트를 발생시킨다.

 

created() 에 해당 코드를 사용했으므로

컴포넌트가 생성될 때 이벤트가 발생하게 된다.

첫 번째 인자는 이벤트의 이름이고, 이후 추가되는 모든 인자는 이벤트 리스너에 전달된다.

 

부모는 v-on을 사용하여 자식 컴포넌트에서 발송한 이벤트를 수신할 수 있다.

<ChildComp @response="(msg) => childMsg = msg" />

response라는 이벤트를 수신하면, 옆에 정의된 메서드를 실행시켜서 childMsg를 msg로 변경하게 된다.

// ChildComp.vue
<script>
export default {
  emits: ['response'],
  created() {
    this.$emit('response', '자식 컴포넌트로부터 🌷를 받았어요!')
  }
}
</script>

<template>
  <h2>자식 컴포넌트</h2>
</template>
// App.vue
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      childMsg: '자식 컴포넌트로부터 아직 메시지를 받지 못했어요!'
    }
  },
}
</script>

<template>
  <ChildComp v-on:response="(msg) => childMsg = msg"/>
  <p>{{ childMsg }}</p>
</template>

 

 

슬롯)

부모 컴포넌트는 자식에게 props를 사용하여 데이터를 전달하는 것 외에도, 

슬롯을 사용하여 템플릿 조각을 전달할 수 있다.

// ChildComp.vue
<template>
  <slot>대체: 부모로부터 컨텐츠를 못 받았어요! 😢</slot>
</template>
// App.vue
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      msg: 'Vue는 개발자에게 정말 유용하죠! 🎁'
    }
  }
}
</script>

<template>
  <ChildComp>{{ msg }}</ChildComp>
</template>

 

'간단 요약' 카테고리의 다른 글

221206 SQLD 학습  (0) 2022.12.07
데이터 모델링 Day 1  (0) 2022.08.01
220404 Java 14장 스트림 간단 요약  (0) 2022.04.05

+ Recent posts