emit
<script setup>안에서의 props 와 component와 v-model을 통한 양방향 바인딩

props 기본에 이어쓰는 포스팅

emit

1. 마크업에서 바로 emit사용

자식Component

PostCreate.vue 작성


<button @click="$emit('createEmit', 'Parameter1', 'Parameter2')">
  button
</button>

2번째인자부터는 전달할 인자이다.

$emit만을 사용할땐 아래처럼 js에서 emit을 따로 선언할 필요가 없다.

const emit = defineEmits({
  'createEmit': null, 
  
  //another Emit
  'createPost': null
})

하지만 다른emit 함수($emit이 아닌 함수)와 같이 사용하려면 $emit여도 emit에 등록해줘야한다

부모component

<script setup>
  const emitTest = (param1, param2) => {
    console.log('emitTest', param1, param2);
  }
<script>

<template>
  <PostCreate @createEmit="emitTest"></PostCreate>
</template>
emitTest Parameter1 Parameter2

2.js에서 emit 사용

자식 component

html

<input type="text" v-model="title"/>
<select v-model="type">
  <option selected>Open this select menu</option>
  <option value="news">뉴스</option>
  <option value="notice">공지사항</option>
</select>
<button @click="createPost">
  button2
</button>

input태그에 title로 사용할 값을 입력하고 select태그에 글의 type을 지정해주자
그리고 버튼클릭시 createPost이벤트를 실행시키고 이벤트안에서 emit를 실행하여 부모component에게 전달하자

js

const emit = defineEmits({
  'createPost': null, 
})

const createPost = () => {
  emit('createPost', newPost); //부모에게 createPost 함수를 발생시킴
}

<script setup>을 사용하지않고 <script>를 사용할땐 setup(props, context)에서 context를 가져오고 context에서 emit를 가져올수있다

context.emit = ['createPost']

하지만 <script setup>에서는 context를 가져올 수 없으므로 defineEmits()를 사용한다

부모 component

<script setup>
  const createPost = (newValue) =>{
    posts.push(newValue)
  }
</script>

<template>
<PostCreate @createEmit="emitTest" @createPost="createPost"></PostCreate>
</template>

여기서 posts지난 번 포스팅 props에서 설명하였다

3. validation 넣기

위 emit함수에 검증을 넣어줄수 있다

자식component

const emit = defineEmits({
  'createEmit': null, 

  //validation 가능
  'createPost': newValue => {
    if(newValue.type || newValue.title){
      return true
    }
    return false
  },
})

component와 v-model

input태그에는 v-model로 양방향 바인딩을 할 수 있었다.
component에서도 양방향바인딩이 가능하다

1. modelValue 사용

부모component

TheView

<script setup>
  const username = ref('defaultName');
  const changeUserName = (value) =>{
    username.value = value;
  }
</script>

<template>
  <LabelInput
              :modelValue="username"
              @update:modelValue="changeUserName">
  </LabelInput>
  { username }
</template>

modelValue는 양방향데이터할 key값이다. 이제 자식component의 props.modelValue로 전달된다
즉 부모 자기자신의 username과 자식의 props.modelValue를 이용하여 서로 연결된다 어떤놈을 modelValue로 선정할까? username으로 하자! modelValue으로 선정된 username은 값이 변경되면 changeUserName()을 실행한다 자식놈은 이걸 props.modelValue로 인식한다

자식component

js

const props = defineProps({
  modelValue: String,
});


html


{{ label }}
<input 
      type="text"
      :value="modelValue" <!--props.modelValue  같음-->
      @input="event => $emit('update:modelValue', event.target.value)"
/>

image
input에 값을 입력할때마다 부모의 데이터 username이 반응형으로 잘 나타난다


2.v-model 사용

부모 component

<!-- <LabelInput
            :modelValue="username"
            @update:modelValue="changeUserName">
</LabelInput> -->
<LabelInput v-model="username" label="이름1"></LabelInput>

이때 usernamechangeUserName()처럼 변경감지할때 자동으로 변수를 갱신한다

자식 component

자식 component는 딱히 코드를 추가안하여도 정상적으로 동작한다.
하지만 아래처럼 computed를 사용하여 간단하게 줄일 수 있다

<input 
      type="text"
      :value="modelValue" 
      @input="event => $emit('update:modelValue', event.target.value)"
/>
<!-- 위 코드는 아래와 같다-->
<input v-model="value" />

js에서 computed 변수를 선언해주자

const value = computed(
  {
    get() {
      return props.modelValue;
    },
    set(inputValue) {
      emit('update:modelValue', inputValue);
    }
  }
)

const emit = defineEmits({
  'update:modelValue': null,
})

3.v-model에 식별자 추가

부모 component

<LabelInput v-model:title="username" label="이름2"></LabelInput> 

title이라는 식별자 선언
이제 자식component의 props.title로 전달된다(기존에는 props.modelValue로 전달됨)
즉 부모 자기자신의 username과 자식의 props.title를 이용하여 서로 연결된다

자식 component

const props = defineProps({
  //modelVue custom
  title: String,
});

const value = computed(
  {
    get() {
      return props.title;
    },
    set(inputValue) {
      emit('update:title', inputValue);
    }
  }
) //html에서 computed를 사용안할땐 선언할 필요 없다
<!-- html에서 set함수 선언방법 -->
<!-- js에서 computed를 사용안할때 방법-->
<input 
      type="text"
      :value="title" 
      @input="event => $emit('update:title', event.target.value)"
		/>

<!-- js에서 computed를 사용할때 방법-->
<input v-model="value" />

참고자료: Vue3 완벽 마스터: 기초부터 실전까지 - “기본편”

소스코드 바로확인하기

댓글 쓰기