목차
목차1. Vue 5화 (Day38) - 컴포넌트1. 컴포넌트 등록1-1. 컴포넌트 이름1-2. 전역/지역 등록2. 컴포넌트 props. (29m)2.1. 정적/동적 props 전달2-2. 단방향 데이터 흐름2-3 prop의 유효성검사2-4. 컴포넌트 non-prop (16m) - 다시듣기3. 컴포넌트 커스텀 이벤트 (26m)3.1 커스텀 이벤트 정의하기3.2 v-model 인자4. 컴포넌트 Slots (18m, 2배속 필기 최소화)5. 동적 컴포넌트 (10m, 2배속 필기 최소화)6. Refs (21m, 2배속 필기 최소화)
1. Vue 5화 (Day38) - 컴포넌트
1. 컴포넌트 등록
컴포넌트 이름
, 전역/지역 등록
, 모듈시스템
1-1. 컴포넌트 이름
영문 소문자
만 사용
하이픈
사용
- 이름 대소문자 규칙
- SFC(SingleFileComponent)내에서는
파스칼 케이스(MyComponentName)
으로 지정
1-2. 전역/지역 등록
tip
일반적으로는 지역등록을 권장하고, button과 같이 자주 사용되는 컴포넌트만 전역으로 등록- 전역등록
at main.js
app.component(’컴포넌트이름’, import한 컴포넌트)
로 등록- 원하는 vue 파일의 template에서 ‘컴포넌트이름’ 으로 import 없이 바로 사용
- 지역등록
at 원하는 사용 컴포넌트 파일.vue
- import 컴포넌트 후 ,
components:{Hello: Hello}
의 객체로 등록
2. 컴포넌트 props. (29m)
props전달
, prop유효성검사
2.1. 정적/동적 props 전달
props란, 컴포넌트 밖의 data를 컴포넌트 안으로 넣어주는 것 v-bind(:)를 통해 동적인 data도 전달 가능
- 정적 전달
<blog-post title="Vue와 떠나는 여행"></blog-post>
- 동적 전달
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>
- 객체의 속성 전달
- 객체의 경우 각 속성을 모두 작성하는 것이 아니라,
v-bind=’객체명’
을 통해 객체의 모든 속성을 한 번에 넣어줄 수 있다.
2-2. 단방향 데이터 흐름
- props의 경우 부모에서 자식으로 흐르지만, 자식에서 부모로 올라갈 수 는 없다.
- 즉 prop를 수정하려고 시도하면 안된다!
- data 흐름을 파악하기 쉽도록 하는 규칙
- prop을 변경하는 2가지 경우
- 초기값을 prop으로 사용하는 경우
- data속성으로 이 prop값을 지정하여, 해당 data를 수정하여 사용하기
- prop이 변환해야하는 원시 값인 경우
- computed 속성으로 props로 들어온 값을 변경한 값을 사용
initialProps 예시
props: ['initialCounter'], data() { return { counter: this.initialCounter } }
size 코드 예시
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
2-3 prop의 유효성검사
- 해당 컴포넌트에서 props 속성에서 props를 2가지 방법으로 받을 수 있다.
- 배열 형식 :
props: [id, tile, email, ...]
- 객체형식:
props : { id: Number, title:[String, Numnber], email:String }
- 객체형식을 사용할 경우, key값으로 props명, value로 해당 prop의 type을 명시해야한다.
- 여러개 Type이 가능한 경우 배열로 표기한다.
- prop의 default 값을 지정하고 싶은 경우, 객체 리터럴 방식을 통해
‘default’
라는 속성의 값으로 정의한다. required
속성을 통해 필수 값을 지정할 수 있다.
code 예시
export default { props: { id: { type:Number, required:true, }, title: String, email: { type: String, default: "outwater!!", }, }, }
주의
기본적으로 null, undefined는 모든 유효성 검사를 통과한다.
- 커스텀 유효성 검사 함수 추가 가능
custom 유효성 검사 code
propF: { validator: function(value){ return ['success', 'warning', 'danger'].indexOf(value) !== -1 } }
2-4. 컴포넌트 non-prop (16m) - 다시듣기
- 최상위 요소가 여러 개일 경우 inline 스타일이 적용되지 않는 경우
- 상위요소의 속성정보(
$attrs
)를 가져와 등록하는 것으로 해결할 수 있다. :class = $attrs.class
,:style=$attrs.style
,@click=”$attres.onClick”
코드 예시

3. 컴포넌트 커스텀 이벤트 (26m)
emit
, event 유효성검사
3.1 커스텀 이벤트 정의하기
- 1. 자식요소의 event핸들러를 $emit(’customEventName’)으로 지정
<div @click=”$emit(’customEventName’)”>
- 2. 부모요소에서 자식요소에서 지정한 customEventName을 캐치하여 특정 동작하도록 등록
<div @please=”reverseMsg”>
- methods 속성에 reverseMsg 정의하기
Tip
자식요소에서 emit을 등록한customEventName
을emits 속성의 배열 형태로 명시
해주어서, 해당 컴포넌트에서 어떤 customEvent들을 가지고 있는 지 관리할 수 있다. (필수는 아니지만 권장됨
!)emits : [”customEventName1”, ”customEventName2”, ...]
- 객체 형식으로 선언함으로써 Emit된 event들을 명시할 뿐만 아니라, 유효성검사를 진행할 수 있다.
- 유효성 검사 진행하지 않으면 null 입력, 유효성검사 인자에 따라 true/false를 반환하도록 구성
주의
단 false를 리턴하여도, 이벤트함수 자체는 실행됨
email, password 유효성검사 예제
// html <button @submit="submitForm">제출</button> // js app.component('custom-form', { emits: { // 검사 절차 없음 click: null, // submit 이벤트 검사 submit: ({ email, password }) => { if (email && password) { return true } else { console.warn('잘못된 이벤트 페이로드입니다!') return false } } }, methods: { submitForm() { this.$emit('submit', { email, password }) } } })
3.2 v-model 인자
props로 받은 data를 v-model에서 사용하면, 양방향 바인딩을 하게 되므로 props의 변경을 유발하여 사용불가하다. 이때 에는 —
- input 변경 예제
- 부모요소에서 v-bind(:)로 data props로 내려준다. (
:message =”msg”
) - 자식요소에서 props로 message를 등록하고, input의 value 값으로 message를 지정한다
props:[’message’]
&<input :value=”message” />
- 자식요소에서 ‘update’ 라는 커스텀이벤트를 만들고 input변경 메서드에 $emit으로 등록한다. 이때 현재 input의 값을 두번째 인자로 같이 보낸다.
<input @input =”$emit(’update’, $event.target.value)” />
- App.vue
- HelloItem.vue
input 변경 전체 코드
<template> <h1>{{ msg }}</h1> <Hello :message="msg" @update="msg = $event" /> </template>
<template> <div> <label> <input :value="message" @input="$emit('update', $event.target.value)" /> </label> </div> </template> <script> export default { props: { message: { type: String, default: "", }, }, </script>
컴포넌트 단위에서 v-model을 통해 단순화 하기
- 양방향 바인딩을 하고 있는 data임을 modelValue를 통해 알려서 v-model 사용가능
주의
꼭 value의 이름이 ‘modelValue’ 가 아니여도 됨- 부모에서
v-model:customName
으로 지정해줄 수 있음 (해당 이름을 input :value=”customName
” 및 emit의 update:customName
부분에 같은 이름으로 사용하면 됨)
- before (부모)
<Hello :message="msg" @update="msg = $event" />
- before (자식)
<input :value="message" @input="$emit('update', $event.target.value)" />
- after (부모)
<Hello v-model=”msg” />
- after
- html
- props
props: {modelValue :{type, default}}
<input :value="modelValue"
@input="$emit('update:modelValue', $event.target.value)" />
4. 컴포넌트 Slots (18m, 2배속 필기 최소화)
- slot은 컴포넌트의 태그들 사이에 해당하는 값을 출력하고 있는 태그를 말함
- 부모컴포넌트:
<Component>{value}</Component>
⇒ 자식 컴포넌트:<slot>{value} </slot>
- 기본 사용 예제 코드
- 부모 컴포넌트
- 자식 컴포넌트 (Hello)
코드 보기
<template> <Hello> <template #abc> <h1>SlotContent ABC</h1> </template> <template #xyz> <h1>SlotContent XYZ</h1> </template> </Hello> </template>
<template> <slot name="abc" /> <h1>Title</h1> <slot name="xyz" /> </template>
- fallback Content
- 컴포넌트 사이의 값이 없을 때 기본값으로 출력되는 value를 의미
<slot> fallbackContent 작성 </slot>
- 컴포넌트 사이의 여러개의 태그가 존재하는 경우 template으로 범위와 name을 지정하여, 서로 다른 위치에 자리하도록 할 수 있다.
- v-slot:abc v-slot:xyz
- v-slot의 약어로 ‘
#
’ 기호 사용 가능 #abc, #xyz
- 범위를 갖는 Slot 은 문서 참고하기!
5. 동적 컴포넌트 (10m, 2배속 필기 최소화)
<component :is="componentName" />
디렉티브로 사용하며, 해당 data의 여부에 따라 컴포넌트의 렌더링 여부를 결정할 수 있음
- 주로 navBar 에서 클릭을 통해 해당 페이지컴포넌트를 불러오는 등에 활용된다.
- 클릭을 통해 현재 컴포넌트 바꿔서 렌더링 하는 예제
코드 보기
<template> <button @click="currentComponent = 'Hello'">Hello</button> <button @click="currentComponent = 'World'">World</button> <component :is="currentComponent" /> </template>
- keep-alive 태그를 통해, 캐싱하여 렌더링 최적화 하기
- 동적으로 자주 변화가 있는 컴포넌트만 keep-alive 사용할 것 (메모리사용하므로)
6. Refs (21m, 2배속 필기 최소화)
자식 컴포넌트의 html 요소를 직접 접근할 때 사용
문제
domAPI를 사용하면, 전체 트리 구조에서 검색을 진행해서 프로젝트가 커지면 부담이 갈 수 있다는 단점
해결
현재 컴포넌트 내부에서만 검색범위를 좁히도록 함<h1 ref=”hello”>
⇒this.$refs.hello
로 탐색 가능
주의
mounted() 시점 이전에는 렌더링이 되지 않으므로 사용할 수 없다.- 컴포넌트 단위에서 ref 적용하기
- Vue app이 기본으로 가지는
$refs
속성을 통해 해당 컴포넌트에 접근하고, 해당 컴포넌트의 $el로 요소 접근한다. <Hello ref=”hello” />
⇒this.$refs.hello.$el
주의
최상위 요소가 여러개 일 때는 $el에 특정요소가 잡히지 않는다.해결
해당 컴포넌트 내부에서 필요한 요소의 ref를 걸어주고 접근this.$refs.hello.$refs.world
- input ref를 찾아 foucs 해보는 예제
코드보기
// Html <div v-if="!isEdit"> {{ msg }} <button @click="onEdit">Edit</button> </div> <div v-else> <input ref="input" v-model="msg" type="text" @keyup.enter="isEdit = false" /> </div>
// js import { nextTick } from "@vue/runtime-core"; export default { data() { return { msg: "hello vue!", isEdit: false, }; }, methods: { onEdit() { this.isEdit = !this.isEdit; nextTick(() => { this.$refs.input.focus(); }); // setTimeout(() => { // this.$refs.input.focus(); // }); }, }, };
