[Vue] Component State Flow

Jingi·2024년 5월 13일

Web

목록 보기
36/40
post-thumbnail

Passing Props

Props

  • 부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하는데 사용되는 속성

Props 특징

  • 부모 속성이 업데이트되면 자식으로 전달 되지만 그 반대는 안됨
  • 즉, 자식 컴포넌트 내부에서 props를 변경하려고 시도해서는 안되며 불가능
  • 또한 부모 컴포넌트가 업데이트될 때마다 이를 사용하는 자식 컴포넌트의 모든 props가 최신 값으로 업데이트됨
    • 부모 컴포넌트에서만 변경하고 이를 내려 받는 자식 컴포넌트는 자연스럽게 갱신

One-Way Data Flow

  • 모든 props는 자식 속성과 부모 속성 사이에 하향식 단방향 바인딩을 형성
  • 단방향인 이유
    • 하위 컴포넌트가 실수로 상위 컴포넌트의 상태를 변경하여 앱에서의 데이터 흐름을 이해하기 어렵게 만드는 것을 방지하기 위함
      • 데이터 흐름의 "일관성" 및 "단순화"

Props 선언

  • 부모 컴포넌트에서 내려 보낸 props를 사용하기 위해서는 자식 컴포넌트에서 명시적인 props 선언이 필요
  • defineProps()를 사용하여 props를 선언
  • defineProps()에 작성하는 인자의 데이터 타입에 따라 선언 방식이 나뉨
    <script setup>
      defineProps()
    </script>

Props 선언 2가지 방식

  • 문자열 배열을 사용한 선언
  • 객체를 사용한 선언

문자열 배열을 사용한 선언

  • 배열의 문자열 요소로 props 선언
  • 문자열 요소의 이름은 전달된 props의 이름
    <script setup>
    defineProps(['myMsg'])
    </script>

객체를 사용한 선언

  • 각 객체 속성의 키가 전달받은 props 이름이 되며, 객체 속성의 값은 값이 될 데이터의 타입에 해당하는 생성자 함수여야 함
    <script setup>
    defineProps({
      myMsg:String
    })
    </script>

props 데이터 사용

  • props 선언 후 템플릿에서 반응현 변수와 같은 방식으로 활용

    <div>
      <p> {{ myMsg }} </p>
    </div>
  • props를 객체로 반환하므로 필요한 경우 JavaScript에서 접근 가능

    <script setup>
    const props = defineProps({myMsg:string})
    console.log(props) // {myMsg:'message'}
    console.log(props.myMsg) // message
    </script>
    

Props 작성

  • 부모 컴포넌트 Parent에서 자식 컴포넌트 ParentChild에 보낼 props 작성
    <template>
      <div>
        <ParentChild my-msg="message" />
      </div>
    </template>

한 단 계 더 props 내려 보내기

  • ParentChild 컴포넌트를 부모로 갖는 ParentGrandChild 컴포넌트 생성 및 등록

    <!-- ParentGrandChild.vue -->
    <template>
      <div>
        <p>{{ myMsg }}</p>
      </div>
    </template>
    <script setup>
    defineProps({
      myMsg:String,
    })
    </script>
    <template>
      <div>
        <p>{{ myMsg }}</p>
        <ParentGrandChild :my-msg="myMsg"/>
      </div>
    </template>
    <script setup>
    import ParentGrandChild from '@/components/ParentGrandChild.vue'
    
    defineProps({
      myMsg:String,
    })
    </script>

Props 세부사항

  • Props Name Casing
  • Static Props 와 Dynamic Props

Props Name Casing

  • 자식 컴포넌트로 전달 시 (->kebab-case)
    • <ParentChild my-mgs="message" />
  • 선언 및 템플릿 참조시 (-> camelCase)
    defineProps({
      myMsg:String
    })
    <p>{{myMsg}}</p>

Props 활용

  • vfor와 함꼐 사용하여 반복되는 요소를 props로 전달하기

  • ParentItem 컴포넌트 생성 및 Parent의 하위 컴포넌트로 등록

    <!-- ParentItem.vue -->
    <template>
      <div>
        
      </div>
    </template>
    <script setup>
    </script>
    <!-- Parent.vue -->
    <template>
      <div>
        <ParentItem/>
      </div>
    </template>
    <script setup>
    import ParentItem from '@/components/ParentItem.vue'
    </script>
  • 데이터 정의 및 v-for 디렉티브의 반복 요소로 활용

  • 각 반복 요소를 props로 내려 보내기

    <!-- Parent.vue -->
    const items = ref([
      {id : 1, name : '사과'},
      {id : 2, name : '바나나'},
      {id : 3, name : '딸기'}
    ])
    <!-- Parent.vue -->
    
    <ParentItem
      v-for="item in items"
      :key="item.id"
      :my-prop="item"
    />
  • props 선언 및 출력 결과 확인

    <!-- ParentItem.vue -->
    
    <template>
      <div>
        <p>{{ myProp.id }}</p>
        <p>{{ myProp.name }}</p>
      </div>
    </template>
    
    <script setup>
    defineProps({
      myProp:Object
    })
    </script>

Component Events

Emit

  • 부모는 자식에게 데이터를 전달하며, 자식은 자신에게 일어난 일을 부모에게 알림
    • 부모가 props 데이터를 변경하도록 소리쳐야 한다.

$emit(event, args)

  • 자식 컴포넌트가 이벤트를 발생시켜 부모 컴포넌트로 데이터를 전달하는 역할의 메서드
  • event
    • 커스텀 이벤트 이름
  • args
    • 추가 인자

이벤트 발신 및 수신

  • $emit을 사용하여 템플릿 표현식에서 직접 사용자 정의 이벤트를 발신
    • <button @click="emit('someEvent')"> 클릭 </button>
  • 그런 다음 부모는 v-on을 사용하여 수신할 수 있음.
    • <ParentComp @some-event="someCallback"/>

emit 이벤트 선언

  • defineEmits()를 사용하여 발신할 이벤트를 서언

  • props와 마찬가지로 defineEmits()에 작성하는 인자의 데이터 타입에 따라 선언 방식이 나뉨(배열, 객체)

  • defineEmits()는 $emit 대신 사용할 수 있는 동등한 함수를 반환

    <script setup>
    defineEmits()
    </script>
    
    <script setup>
    const emit = defineEmits(['someEvent', 'myFocus'])
    const buttonClick = function(){
      emit('someEvent')
    }
    </script>

이벤트 선언 활용

  • 이벤트 선언 방식으로 추가 버튼 작성 및 결과 확인

    <!-- ParentChild.vue -->
    <script src>
    const emit = defineEmits(['someEvent'])
    
    const buttonClick = function(){
      emit('someEvent')
    }
    </script>
    <template>
    <button @click="buttonClick">클릭</button>
    </template>

이벤트 인자

  • 이벤트 발신 시 추가 인자를 전달하여 값을 제공할 수 있음

이벤트 인자 전달 활용

  • ParentChild에서 이벤트를 발신하여 Parent로 추가 인자 전달하기

    <!-- ParentChild.vue -->
    
    const emit = defineEmits(['someEvent','emitArgs'])
    
    const emitArgs = function(){
      emit('emitArgs',1 ,2 ,3)
    }
    <!-- ParentChild.vue -->
    <button @click = "emitArgs">추가 인자 전달</button>
    <!-- Parent.vue -->
    <ParentChild
    @some-event="someCallback"
    @emit-args = "getNumbers"
    my-msg ="message"
    :dynamic-props="name"
    />
    <!-- Parent.vue -->
    const getNumbers = function(...args){
      console.log(args)
      console.log(`ParentCild가 전달한 추가인자 ${args}를 수신했어요 `)
    }

Event Name Casing

  • 선언 및 발신 시

    <button @click="$emit('someEvent')">클릭</button>
    const emit = defineEmits(['someEvent'])
    emit('someEvent')
  • 부모 컴포넌트에서 수신 시

    <ParentChild @some-event="..."/>

emit 이벤트 활용

  • 이벤트 수신 후 이름 변경을 요청하는 이벤트 발신

    // ParentChild.vue
    const emit = defineEmits(['someEvent','emitArgs', 'updateName'])
    
    const updateName = function(){
      emit('updateName')
    }
    // ParentChild.vue
    <ParentGrandChild :my-msg="myMsg" @update-name="updateName"/>
  • 이벤트 수신 후 이름 변수 변경 메서드 호출

  • 해당 변수를 props으로 받는 모든 곳에서 자동 업데이트

    <ParentChild @update-name="updateName"/>
    
    const updateName = function(){
      name.value = 'Bella'
    }
profile
데이터 분석에서 백엔드까지...

0개의 댓글