Vue.js에서 구성 요소 간에 데이터를 전달하는 방법

게시 됨: 2022-03-10
빠른 요약 ↬ 구성 요소 간에 데이터를 공유하는 다양한 방법이 있으므로 상황에 가장 적합한 기술을 알아야 합니다. VueJS에서 데이터를 전달하는 가장 일반적인 세 ​​가지 방법을 분석해 보겠습니다.

구성 요소 간에 데이터를 공유하는 것은 VueJS의 핵심 기능 중 하나입니다. 이를 통해 보다 모듈화된 프로젝트를 설계하고, 데이터 범위를 제어하고, 앱 전체에서 자연스러운 데이터 흐름을 생성할 수 있습니다.

하나의 구성 요소에서 전체 Vue 앱을 생성하지 않는 한(이는 의미가 없음) 구성 요소 간에 데이터를 공유해야 하는 상황에 직면하게 됩니다.

이 튜토리얼이 끝나면 이 작업을 수행하는 세 가지 방법을 알게 될 것입니다.

  • props를 사용하여 부모에서 자식으로 데이터 공유,
  • 자식에서 부모로 데이터를 공유하기 위해 사용자 지정 이벤트를 내보내고,
  • Vuex를 사용하여 앱 수준 공유 상태 만들기.

좋아 — 바로 들어가 봅시다!

Nuxt로 앱 빌드

Spotify를 사용하면 친구들이 내가 무엇을 방해하고 있는지 확인할 수 있습니다. 인터넷의 나머지 부분도 당신의 알고리즘을 경험할 수 있다면 어떨까요? Vue.js 및 Nuxt를 사용하여 Spotify에서 듣고 있는 내용을 공유하기 위해 자신의 앱을 구성하는 방법을 알아보세요. 관련 기사 읽기 →

점프 후 더! 아래에서 계속 읽기 ↓

1. Props를 사용하여 부모에서 자식으로 데이터 공유

VueJS props는 컴포넌트 간에 데이터를 공유하는 가장 간단한 방법입니다. Props는 컴포넌트에 부여할 수 있는 사용자 정의 속성입니다. 그런 다음 템플릿에서 이러한 속성 값을 제공할 수 있으며 — BAM — 데이터를 상위 구성 요소에서 하위 구성 요소로 전달합니다!

예를 들어 사용자 프로필 페이지에서 작업 중이고 자식 구성 요소가 사용자 이름 소품을 수락하도록 하려고 한다고 가정해 보겠습니다. 두 가지 구성 요소가 필요합니다.

  1. prop을 수락하는 자식 구성 요소를 AccountInfo.vue 라고 합시다.
  2. prop을 전달하는 부모 컴포넌트를 ProfilePage.vue 라고 합시다.

AccountInfo.vue 내부에서 props 옵션을 사용하여 수락하는 props를 선언할 수 있습니다. 따라서 컴포넌트 옵션 내부에서 다음과 같이 보이도록 해보자.

 // AccountInfo.vue <template> <div id='account-info'> {{username}} </div> </template> <script> export default { props: ['username'] } </script>

그런 다음 실제로 부모( ProfilePage.vue )의 데이터를 전달하기 위해 사용자 지정 속성처럼 전달합니다.

 // ProfilePage.vue <account-info username='matt' />

이제 페이지를 로드하면 AccountInfo 구성 요소가 부모가 전달한 값을 올바르게 렌더링하는 것을 볼 수 있습니다.

다른 VueJS 지시어로 작업할 때와 마찬가지로 v-bind를 사용하여 props를 동적으로 전달할 수 있습니다. 예를 들어, 사용자 이름 prop을 변수와 동일하게 설정하고 싶다고 가정해 봅시다. v-bind 지시문(또는 간단히 : 에 대한 약식을 사용하여 이를 수행할 수 있습니다. 코드는 다음과 같습니다.

 <template> <div> <account-info :username="user.username" /> </div> </template> <script> import AccountInfo from "@/components/AccountInfo.vue"; export default { components: { AccountInfo }, data() { return { user: { username: 'matt' } } } } </script>

즉, 데이터를 변경할 수 있고 해당 값을 사용하는 자식 소품도 업데이트됩니다.

팁: 항상 소품을 확인하세요

보다 명확한 Vue 코드를 작성하려는 경우 중요한 기술은 props를 확인하는 것입니다. 간단히 말해서, 이는 소품에 대한 요구 사항(예: 유형, 형식 등)을 지정해야 함을 의미합니다. 이러한 요구 사항 중 하나가 충족되지 않으면(예: prop이 잘못된 유형으로 전달된 경우) Vue는 경고를 출력합니다.

사용자 이름 소품이 문자열만 허용하기를 원한다고 가정해 봅시다. props 객체를 다음과 같이 수정해야 합니다.

 export default { props: { username: String } }

대규모 Vue 앱에서 작업하거나 플러그인을 디자인할 때 props 확인은 필수입니다. 모든 사람이 같은 페이지에 있는지 확인하고 의도한 대로 소품을 사용하도록 합니다.

props에 포함할 수 있는 검증의 전체 목록을 보려면 공식 문서에서 심층 검토를 확인하는 것이 좋습니다.

팁: 소품 명명 규칙을 따르세요

VueJS 스타일 가이드에 따르면 props의 이름을 지정하는 가장 좋은 방법은 스크립트에서 선언할 때 camelCase 를 사용하고 템플릿 코드에서 참조할 때 kebab-case를 사용하는 것입니다.

이에 대한 근거는 사실 아주 간단합니다. Javascript에서 camelCase 는 표준 명명 규칙이고 HTML에서는 kebab-case입니다.

따라서 Vue는 각 언어의 표준을 준수할 것을 권장합니다. 고맙게도 Vue는 두 스타일 사이를 자동으로 변환할 수 있으므로 개발자를 위한 추가 설정이 없습니다.

 // GOOD <account-info :my-username="user.username" /> props: { myUsername: String } // BAD <account-info :myUsername="user.username" /> props: { "my-username": String }

2. 자식에서 부모로 데이터를 공유하는 이벤트 방출

이제 계층 구조를 따라 전달되는 데이터가 있으므로 다른 방법으로 전달해 보겠습니다. 자식 구성 요소에서 부모로 전달합니다. 소품은 사용할 수 없지만 사용자 정의 이벤트와 리스너는 사용할 수 있습니다.

모든 Vue 인스턴스는 이벤트를 트리거하는 .$emit(eventName) 메서드를 호출할 수 있습니다. 그런 다음 v-on 지시문을 사용하여 다른 이벤트와 동일한 방식으로 이 이벤트를 수신할 수 있습니다.

사용자 정의 이벤트 생성

사용자 이름을 변경하는 버튼을 추가하여 사용자 프로필 예제를 빌드해 보겠습니다. 자식 구성 요소( AccountInfo.vue ) 안에 버튼을 만들어 보겠습니다.

그런 다음 이 버튼을 클릭하면 changeUsername 이라는 이벤트가 발생합니다.

 <template> <div id='account-info'> <button @click='changeUsername()'>Change Username</button> {{username}} </div> </template> <script> export default { props: { username: String }, methods: { changeUsername() { this.$emit('changeUsername') } } } </script>

부모 내부에서 이 이벤트를 처리하고 user.username 변수를 변경합니다. 앞에서 논의한 것처럼 v-on 지시문 또는 줄여서 "@"를 사용하여 이벤트를 수신할 수 있습니다.

 <template> <div> <account-info :username="user.username" @changeUsername="user.username = 'new name'"/> </div> </template>

시도해 봅시다. 버튼을 클릭하면 사용자 이름이 "새 이름"으로 변경되는 것을 볼 수 있습니다.

팁: 사용자 정의 이벤트는 인수를 허용할 수 있습니다.

이벤트에 인수를 전달하는 가장 일반적인 사용 사례는 하위 구성 요소가 해당 소품에 대한 특정 값을 설정할 수 있기를 원하는 경우입니다. 구성 요소 자체에서 소품 값을 직접 편집하고 싶지는 않습니다 .

그러나 운 좋게도 사용자 지정 이벤트와 함께 전달 인수를 사용하여 상위 구성 요소가 값을 변경하도록 할 수 있습니다.

값을 전달할 수 있도록 changeUsername 이벤트를 수정한다고 가정해 보겠습니다.

$emit 메소드는 인수에 대해 선택적 두 번째 매개변수를 사용합니다. 따라서 우리가 하는 일은 이벤트 이름 뒤에 새 사용자 이름 값을 추가하는 것뿐입니다.

 this.$emit('changeUsername', 'mattmaribojoc')

그런 다음 상위 구성 요소에서 특수 $event 변수를 사용하여 이러한 값에 인라인으로 액세스하거나 매개 변수를 사용하는 처리기 메서드를 작성할 수 있습니다.

 <account-info :username="user.username" @changeUsername="user.username = $event"/> OR <account-info :username="user.username" @changeUsername="changeUsername($event)"/> export default { ... methods: { changeUsername (username) { this.user.username = username; } } }

3. Vuex를 사용하여 애플리케이션 수준 공유 상태 만들기

좋습니다. 부모/자식 간에 데이터를 공유하는 방법을 알고 있지만 다른 구성 요소는 어떻습니까? 데이터를 전달하려면 매우 복잡한 계층 구조 시스템을 만들어야 합니까?

고맙게도 그렇지 않습니다. 훌륭한 Vuex 상태 관리 라이브러리는 수년 동안 개발자의 삶을 단순화해 왔습니다. 간단히 말해서 모든 구성 요소에서 액세스할 수 있는 중앙 집중식 데이터 저장소를 만듭니다.

우리가 이전에 사용한 방법(props / emitting events)에서 각 구성 요소는 구성 요소 간에 공유하는 고유한 데이터 상태를 가지고 있습니다. 그러나 Vuex를 사용하면 모든 공유 데이터를 각 구성 요소가 쉽게 액세스할 수 있는 단일 상태로 추출할 수 있습니다. 이 공유 상태를 상점이라고 합니다.

시도해 봅시다.

Vuex는 Vue의 핵심 코드와 분리되어 있기 때문에 먼저 설치하고 프로젝트에 가져와야 합니다. 먼저 프로젝트 CLI 내에서 npm install vuex --save 를 실행해야 합니다.

그런 다음 다음 코드가 포함된 index.js 파일로 src/store 폴더를 만듭니다.

 // store/index.js import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {} });

루트 Vue 인스턴스에 이것을 포함하려면 store/index.js 파일을 가져와서 Vue 생성자에 전달해야 합니다.

 // main.js import store from "./store"; new Vue({ store, ...

Vue Store 내부 구성 요소에 액세스

루트 Vue 인스턴스에 Vuex 저장소를 추가했으므로 루트의 모든 자식에 주입됩니다. 컴포넌트에서 스토어에 액세스하려면 this.$store 를 통해 액세스할 수 있습니다.

이제 Vuec 스토어의 네 부분 각각의 세부 사항을 살펴보겠습니다.

1. 상태

Vuex 상태는 응용 프로그램 수준 데이터를 포함하는 개체입니다. 모든 Vue 인스턴스는 이 데이터에 액세스할 수 있습니다.

상점의 경우 사용자 프로필 데이터를 더 저장하는 사용자 개체를 만들어 보겠습니다.

 export default new Vuex.Store({ state: { user: { username: 'matt', fullName: 'Matt Maribojoc' } }, getters: {}, mutations: {}, actions: {} });

이와 같은 모든 인스턴스 구성 요소 내에서 이 데이터에 액세스할 수 있습니다.

 mounted () { console.log(this.$store.state.user.username); },

2. 게터

Vuex getter를 사용하여 상태 데이터의 수정된 값을 반환합니다. getter를 생각하는 좋은 방법은 getter를 계산된 속성처럼 취급하는 것입니다. 예를 들어, 계산된 속성과 같은 getter는 결과를 캐시하고 종속성이 수정될 때만 재평가합니다.

이전 저장소를 기반으로 전체 이름 속성을 기반으로 사용자의 이름을 반환하는 메서드를 만들고 싶다고 가정해 보겠습니다.

 getters: { firstName: state => { return state.user.fullName.split(' ')[0] } }

Vuex getter 속성은 store.getters 객체의 구성 요소에서 사용할 수 있습니다.

 mounted () { console.log(this.$store.getters.firstName); }

팁: 기본 Getter 인수를 알고 있습니다.

기본적으로 Vuex getter는 두 개의 인수를 허용합니다.

  1. state — 애플리케이션의 상태 객체.
  2. getters — store.getters 객체, 즉 우리 가게의 다른 getter를 호출할 수 있습니다.

선언하는 모든 getter에는 첫 번째 상태 인수가 필요합니다. 그리고 코드를 디자인하는 방법에 따라 getter는 두 번째 'getters' 인수를 사용하여 서로를 참조할 수 있습니다.

이름 상태 속성에서 이름 값을 단순히 제거하는 성 getter를 만들어 보겠습니다. 이 예제에는 상태 및 getters 개체가 모두 필요합니다.

 lastName (state, getters) { return state.user.fullName.replace(getters.firstName, ''); }

팁: Vuex Getters에 사용자 지정 인수 전달

getter의 또 다른 멋진 기능은 getter가 메서드를 반환하도록 하여 사용자 지정 인수를 전달할 수 있다는 것입니다.

 prefixedName: (state, getters) => (prefix) => { return prefix + getters.lastName; } // in our component console.log(this.$store.getters.prefixedName("Mr."));

3. 돌연변이

돌연변이는 상태 개체의 값을 적절하게 변경하는 유일한 방법입니다. 주목해야 할 중요한 세부 사항은 돌연변이 가 동기적이어야 한다는 것 입니다.

게터와 마찬가지로 돌연변이는 항상 Vuex 상태 속성을 첫 번째 인수로 받아들입니다. 또한 페이로드라고 하는 사용자 지정 인수를 두 번째 인수로 허용합니다.

예를 들어 사용자 이름을 특정 값으로 변경하는 변형을 만들어 보겠습니다.

 mutations: { changeName (state, payload) { state.user.fullName = payload } },

그런 다음 두 번째 인수로 페이로드를 사용하여 store.commit 메서드를 사용하여 구성 요소에서 이 메서드를 호출할 수 있습니다.

 this.$store.commit("changeName", "New Name");

종종 페이로드가 객체가 되기를 원할 것입니다. 이는 돌연변이에 여러 인수를 전달할 수 있을 뿐만 아니라 개체의 속성 이름으로 인해 코드를 더 읽기 쉽게 만든다는 것을 의미합니다.

 changeName (state, payload) { state.user.fullName = payload.newName }

페이로드로 돌연변이를 호출하는 두 가지 다른 방법이 있습니다.

  1. 돌연변이 유형을 첫 번째 인수로, 페이로드를 두 번째 인수로 가질 수 있습니다.
  2. 유형에 대한 속성 하나와 페이로드에 대한 속성 하나를 사용하여 단일 개체 전달을 선언할 수 있습니다.
 this.$store.commit("changeName", { newName: "New Name 1", }); // or this.$store.commit({ type: "changeName", newName: "New Name 2" });

둘의 작동 방식에는 실제 차이가 없으므로 전적으로 개인 취향에 달려 있습니다. 전체 프로젝트에서 일관성을 유지하는 것이 항상 최선임을 기억하십시오. 따라서 어느 쪽을 선택하시든 고수하십시오!

4. 조치

Vuex에서 액션은 상태를 변경하는 데 사용하기 때문에 돌연변이와 상당히 유사합니다. 그러나 작업은 값 자체를 변경하지 않습니다. 대신 작업이 돌연변이를 커밋합니다.

또한 Vuex 돌연변이는 동기적이어야 하지만 작업은 그렇지 않습니다. 예를 들어 작업을 사용하여 API 호출 후 변형을 호출할 수 있습니다.

우리가 본 대부분의 Vuex 핸들러는 상태를 주요 매개변수로 받아들이지만 액션은 컨텍스트 객체를 받아들입니다. 이 컨텍스트 객체를 사용하면 Vuex 저장소의 속성(예: state, commit, getters)에 액세스할 수 있습니다.

다음은 2초를 기다린 다음 changeName 변형을 커밋하는 Vuex 작업의 예입니다.

 actions: { changeName (context, payload) { setTimeout(() => { context.commit("changeName", payload); }, 2000); } }

컴포넌트 내에서 함수를 실행하기 위해 store.dispatch 메소드를 사용합니다. 우리는 돌연변이와 마찬가지로 인수를 전달합니다. 유형을 선언하고 두 번째 인수에 사용자 지정 인수를 전달합니다.

 this.$store.dispatch("changeName", { newName: "New Name from Action" });

마무리

이제 VueJS의 구성 요소 간에 데이터를 공유하는 세 가지 다른 방법인 props, 사용자 지정 이벤트 및 Vuex 저장소를 알아야 합니다.

이 튜토리얼이 다양한 Vue 방법과 모범 사례에 대한 통찰력을 제공하는 데 도움이 되었기를 바랍니다. 프로젝트에 어떻게 구현했는지 알려주세요!

추가 읽기

각 기술의 기술적 측면/기능에 대해 더 자세히 알고 싶다면 여기에서 시작하기에 좋은 곳이 있습니다.

  • Vuex 공식 가이드 웹사이트
  • 소품 및 사용자 정의 이벤트용 VueJS 문서
  • “WTF가 Vuex입니까? Vue의 애플리케이션 데이터 저장소에 대한 초보자 가이드" Anthony Gore, Vue.js 개발자