📒 Data in component
📎 Data in component
- 우리는 정적 웹페이지가 아닌, 동적 웹페이지를 만들고 있음 (다뤄야 할 데이터가 등장)
- 한 페이지 내에서 같은 데이터를 공유해야 함
- 하지만 페이지들은 각각의 component로 구분이 되어있음
- Data를 필요한 컴포넌트끼리 주고받을 경우?
- 데이터의 흐름을 파악하기 힘듦
- 개발 속도 저하
- 유지보수 난이도 증가
- 컴포넌트는 부모-자식 관계를 가지므로, 부모-자식 관계만 데이터를 주고 받게해야함
pass props & emit event
- 부모 => 자식으로의 데이터의 흐름
- 자식 => 부모로의 데이터의 흐름
📎 Pass Props
- 요소의 속성(property)을 사용하여 데이터 전달
- props는 부모(상위) 컴포넌트의 정보를 전달하기 위한 사용자 지정 특성
- 자식(하위) 컴포넌트는 props 옵션을 사용하여 수신하는 props를 명시적으로 선언해야 함
- 요소에 속성을 작성하듯이 사용 가능하여, prop-data-name="value"의 형태로 데이터를 전달
- 이때 속성의 키 값은 kebab-case를 사용 (HTML 속성명은 대소문자를 구분하지 않기 때문)
- 데이터를 받는 쪽, 즉 하위 컴포넌트에서도 props에 대해 명시적으로 작성 해주어야 함
- 전달받은 props를 type과 함께 명시
- 컴포넌트를 문서화할 뿐만 아니라, 잘못된 타입이 전달되는 경우 브라우저의 자바스크립트 콘솔에서 사용자에게 경고
📎 Dynamic props
- 변수를 props로 전달할 수 있음
- v-bind directive를 사용해 데이터를 동적으로 바인딩
- 부모 컴포넌트의 데이터가 업데이트 되면 자식 컴포넌트로 전달되는 데이터 또한 업데이트 됨
📎 단방향 데이터 흐름
- 모든 props는 부모에서 자식으로 단방향 바인딩을 형성
- 부모 속성이 업데이트되면 자식으로 흐르지만 반대 방향은 아님
- 하위 컴포넌트가 실수로 상위 컴포넌트 상태를 변경하여 앱의 데이터 흐름을
이해하기 힘들게 만드는 것을 방지
📎 Emit Event
- 자식 컴포넌트에서 부모 컴포넌트에게 데이터를 전달할 때 $emit 메서드를 통해 이벤트를 발생
- $emit('event-name') 형식으로 사용하며 부모 컴포넌트에
event-name 이라는 이벤트가 발생한 것을 알림
📎 Emit Event 실습
- 자식 컴포넌트에 버튼을 만들고 클릭 이벤트를 추가
- $emit을 통해 부모 컴포넌트에게 child-to-parent 이벤트를 트리거
- 부모 컴포넌트에서 emit된 이벤트를 청취 후 핸들러 함수 실행
📒 Vuex
📎 Pass Props & Emit Event 문제점
- Pass Props & Emit Event 방식은 component 중첩이 깊어지면 데이터 전달이 쉽지 않음
- 공통의 상태를 유지해야 하는 component가 많아지면 데이터 전달 구조가 복잡해짐
📎 Vuex
- "state management pattern + Library" for vue.js (상태 관리 패턴 + 라이브러리)
- 중앙 저장소(store)에 데이터를 모아서 상태 관리를 할 수 있도록 하는 라이브러리
- 각 component는 계층에 상관없이 중앙 저장소에 접근해 데이터를 얻거나 변경할 수 있음
- 데이터가 예측 가능한 방식으로만 변경될 수 있도록 하는 규칙을 설정하며,
Vue의 반응성을 효율적으로 사용하는 상태 관리 기능을 제공
📎 Vuex 구조
📌 State
- vue 인스턴스의 data에 해당
- 중앙에서 관리하는 모든 상태정보
- 개별 component는 state에서 데이터를 가져와서 사용
- state의 데이터가 변화하면 해당 데이터를 사용하는 component도 자동으로 다시 렌더링
- $store.state로 state 데이터에 접근
📌 Mutations (state를 변경)
- 실제로 state를 변경하는 유일한 방법
- vue 인스턴스의 methods에 해당하지만 Mutations에서 호출되는
핸들러(handler) 함수는 반드시 동기적이어야 함
- 비동기 로직으로 mutations를 사용해 state를 병경하는 경우,
state의 변화 시기를 특정할 수 없기 때문
- 첫번째 인자로 state를 받으며, component 혹은 Actions에서 commit() 메서드로 호출됨
📌 Actions (state 변경을 제외한 나머지 로직)
- mutations와 비슷하지만 비동기 작업을 포함할 수 있다는 차이가 있음
- state를 직접 변경하지 않고 commit() 메서드로 mutations를 호출해서 state를 변경
- context 객체를 인자로 받으며, 이 객체를 통해 store.js의 모든 요소와 메서드에 접근할 수 있음
- component에서 dispatch() 메서드에 의해 호출됨
📌 Getters
- vue 인스턴스의 computed에 해당
- state를 활용하여 계산된 값을 얻고자 할 때 사용
state의 원본 데이터를 건들지 않고 계산된 값을 얻을 수 있음
- computed와 마찬가지로 getters의 결과는 캐시(cache) 되며, 종속된 값이 변경된 경우에만 재계산됨
- 첫번째 인자로 state, 두번째 인자로 getter를 받음
그렇다면 모든 데이터를 Vuex에서 관리해야하는가?
- Vuex에서도 여전히 pass props, emit event를 사용하여 상태를 관리할 수 있음
- 개발 환경에 따라 적절히 사용하는 것이 필요
📒 Vuex 실습
📎 state
- $store.state로 접근 가능
- $store.state로 바로 접근하기보다 computed에 정의 후 접근하는 것을 권장
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
export default {
name: 'App',
computed: {
message() {
return this.$store.state.message
},
},
}
</script>
📎 actions
- component에서 dispatch(A, B)에 의해 호출됨
- A : 호출하고자 하는 actions 함수
- B : 넘겨주는 데이터(payload)
- actions의 첫번째 인자는 context
- actions의 두번째 인자는 payload
📎 mutations
- component 또는 actions에서 commit(A, B)를 통해 호출됨
- A : 호출하고자 하는 mutations 함수
- B : payload
- mutation 함수의 첫번째 인자는 state, 두번째 인자는 payload