TechScribe Notes
18_Event(Emit) 본문
1.Event :
자식 컴포넌트에서 부모 컴포넌트로 데이터 전달 또는 트리거의 목적으로 이벤트를 내보내는 것.
이벤트는 emit메서드를 통해 발생시킬 수 있음
2. 이벤트 발생 및 수신
: templete안에서 내장함수 $emit()을 사용하여 직접 커스텀한 이벤트를 내보낼 수 있음
<!--자식컴포넌트-->
<template>
<button @click="$emit('someEvent')">버튼</button>
</template>
<!--부모컴포넌트에서 v-on이나 @을 사용해서 이벤트를 수신한다.-->
<MyComponent @some-event="callFunction" />
<!--once도 사용 가능-->
<MyComponent @some-event.once="callFunction" />
3.이벤트 파라미터
: 이벤트와 함께 특정 값을 내보낼 수 있음. $emit함수 이벤트 명에 추가로 파라미터를 넘길 수 있다.
<!--- 자식 컴포넌트 --->
<template>
<button @click="$emit('someEvent', 'Hello', 'World', '!')">버튼</button>
</template>
<!--- 부모 컴포넌트 --->
<template>
<MyComponent @some-event="callFunction" />
</template>
<script setup>
export default {
setup() {
//부모 컴포넌트에서 파라미터를 받음
const callFunction = (word1, word2, word3) => {
alert(word1, word2, word3);
};
return {
callFunction
}
}
}
</script>
4. 이벤트 선언
emit옵션으로 선언하며 JS코드에서 이벤트를 내보낼 때는 setup()함수 파라미터로 넘어온 context.emit()메서드를 사용할 수 있음.
1) 문자열 배열 선언
//context.emit() 사용
export default {
emits: ['someEvent'],
setup(props, context) {
context.emit('someEvent', 'Hello World!')
}
}
//emit을 객체로 가져옴 (구조분해할당)
export default {
emits: ['someEvent'],
setup(props, { emit }) {
emit('someEvent', 'Hello World!')
}
}
2)객체문법 선언
: validation 로직추가로 유효성 체크 가능. validation없으면 null로 설정.
export default {
emits: {
// 유효성 검사가 없는 이벤트 선언
someEvent: null,
// 유효성 검사가 있는 이벤트 선언
someSubmit: (result) => {
if (email && password) {
return true
} else {
console.warn('result 값이 비어있습니다!')
return false
}
}
},
setup(props, context) {
context.emit('someEvent', 'Hello World!')
}
}
*컴포넌트가 작동하는 방식을 더 문서화하기 위해 모든 이벤트를 정의하는 것이 좋음(선택사항). 그리고 non-prop속성의 리스너 제외 가능.
5. v-model만들기
:컴포넌트 생성 후 해당 컴포넌트에 v-model을 적용하려면 @update:modelValue이벤트를 사용하여 만들 수 있음.
<input v-model="username" />
<--- v-model 작동 --!>
<input
:value="username"
@input="username = $event.target.value"
/>
<-- 컴포넌트 수행 --!>
<LabelInput
:modelValue="username"
@update:modelValue="newValue => username = newValue"
/>
이 컴포넌트 <LabelInput>이 제대로 동작하게 하려면 컴포넌트를 정의 해야함
- modelValue propsfmf :value 속성에 바인딩
-@input이벤트에서 새 @update:modelValue이벤트로 내보냄
<template>
<label>
{{ label }}
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</label>
</template>
<script>
export default {
props: ['modelValue', 'label'],
emits: ['update:modelValue'],
};
</script>
그리고 컴포넌트에 v-model 적용
<LabelInput label="이름" v-model="username" />
6. Computed 이용해서 v-model구현하기
<template>
<label>
{{ label }}
<input type="text" v-model="value" />
</label>
</template>
<script>
import { computed } from 'vue';
export default {
props: ['modelValue', 'label'],
emits: ['update:modelValue'],
setup(props, context) {
const value = computed({
get() {
return props.modelValue;
},
set(value) {
context.emit('update:modelValue', value);
},
});
return {
value,
};
},
};
</script>
-부모 컴포넌트에 다시 데이터나 이벤트를 전달해야할 때 부모 컴포넌트에서는 v-on(@)디렉티브를 사용하여 전달받은 이벤트를 수신할 수 있음. 아래에서는 @enlarge-text로 이벤트를 받아서 postFontSize값을 업데이트하여 폰트크기를 확대하는 기능을 만듬
-이 때 자식 컴포넌트에서는 emits옵션으로 이벤트를 선언하고 $emit 내장 메서드를 호출하여 이벤트를 발생시킬 수 있음.
<-- 1. font사이즈를 반응형으로 선언 --!>
const postFontSize = ref(1);
<-- 2. font사이즈를 반영할 수 있도록 부모 컴포넌트 생성 --!>
<div :style="{ fontSize: postFontSize + 'em' }">
<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
@enlarge-text="postFontSize += 0.1"
/>
</div>
<-- 3. 자식 컴포넌트에서 폰트 크기 변경하는 버튼 추가 --!>
<template>
<article>
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">크게</button>
</article>
</template>
<script>
import { toRefs } from 'vue';
export default {
props: ['title'],
emits: ['enlarge-text'],
setup(props) {
const { title } = toRefs(props);
return {
title,
};
},
};
</script>
<style></style>
7. v-model 전달 인자
:v-model은 컴포넌트에서 modelValue props와 update:modelValue 이벤트로 사용함. 그리고 전달인자로 이런 이름을 수정할 수 있음.
<BookComponent v-model:title="bookTitle" />
<--- 자식 컴포넌트에서 :title 속성으로 정의하고 update:title로 이벤트를 내보냄--!>
<template>
<article>
<strong>책 이름</strong> :
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</article>
</template>
<script>
export default {
props: ['title'],
emits: ['update:title'],
};
</script>
8. 다중 v-model 바인딩
: 전달인자로 컴포넌트에 여러 v-model을 바인딩 할 수 있음.
<BookComponent
v-model:title="bookTitle"
v-model:author="bookAuthor"
/>
<template>
<article>
<strong>도서명</strong> :
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
<br />
<strong>저자</strong> :
<input
type="text"
:value="author"
@input="$emit('update:author', $event.target.value)"
/>
</article>
</template>
<script>
export default {
props: ['title', 'author'],
emits: ['update:title', 'update:author'],
};
</script>
9. v-model 수식어(modifier)핸들링
필요에 따라 v-model 수식어 추가 가능함
ex) 첫 글자를 대문자로 표시하는 capitalize 수식어 만들기
<CustomInput v-model.capitalize="username"></CustomInput>
<---컴포넌트에 추가된 수식어는 modelModifiers props를 통해 컴포넌트에 전달됨--!>
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: { default: () => ({}) },
},
emits: ['update:modelValue'],
setup(props, context) {
// {capitalize: true} 출력
console.log(props.modelModifiers);
},
};
</script>
<--- 이벤트를 내보내기 전에 문자열 첫 글자를 대문자로 만들기 --!>
<template>
<input type="text" :value="modelValue" @input="emitValue" />
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: { default: () => ({}) },
},
emits: ['update:modelValue'],
setup(props, { emit }) {
const emitValue = (e) => {
let value = e.target.value;
if (props.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1);
}
emit('update:modelValue', value);
};
return {
emitValue,
};
},
};
</script>
'project > Vue.js' 카테고리의 다른 글
20_slot (0) | 2024.12.26 |
---|---|
19_Non-Prop 속성(fallthrough속성) (0) | 2024.12.24 |
17_Props (0) | 2024.12.23 |
16_Single-File Component (SFC) (0) | 2024.12.12 |
15_컴포넌트 기초 (0) | 2024.12.12 |