Vue 컴포넌트 커뮤니케이션
vue 컴포넌트와 통신하는 방법은 매우 다양합니다!
I. 소품과$emit
부모 컴포넌트가 자식 컴포넌트에 값을 전달합니다.
부모 컴포넌트는 어떻게 값을 자식 컴포넌트에 전달할까요? 이제 프로퍼티를 소개할 차례입니다.
props 속성: Vue.js에서 props는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하기 위한 메커니즘입니다. 프로퍼티를 사용하면 부모 컴포넌트가 데이터를 자식 컴포넌트로 전달하여 자식 컴포넌트가 해당 데이터를 수신하고 사용할 수 있게 할 수 있습니다.
v-bind를 사용하여 컴포넌트의 프로퍼티를 바인딩하여 부모 컴포넌트의 데이터를 자식 컴포넌트로 전달할 수 있습니다.
<!-- v-bind 바인딩 속성을 사용하여 데이터를 하위 컴포넌트에 전달할 수 있습니다. 여기서 "목록"은 데이터 소스의 데이터 목록을 나타내며, 데이터 소스는 v-bind 바인딩 속성을 사용하여 하위 컴포넌트에 전달할 수 있습니다.>
<List :lists = "lists"/>
그렇다면 자식 컴포넌트는 부모 컴포넌트가 전달한 데이터를 어떻게 가져올까요?
defineProps API: Vue 3에서 defineProps 함수는 함수형 컴포넌트에서 프로퍼티를 선언하고 가져오는 도구입니다. 따라서 defineProps 함수를 하위 컴포넌트로 가져와서 할당을
const {users} = defineProps(['users'])사용자를 가져올 수 있습니다.
// defineProps api 부모 컴포넌트가 전달한 파라미터 가져오기
import { defineProps } from 'vue';
const {users} = defineProps(['users'])//users부모 컴포넌트에서 전달된 데이터의 이름
간단한 구문이 하나 더 제공됩니다.
props:['lists']//lists는 부모 컴포넌트가 전달한 데이터의 이름으로, 배열뿐만 아니라 객체도 될 수 있습니다.
정확한 사용 방법에 대한 사례 연구를 참조하세요:
<!-- App.vue -->
<template>
<div>
<div class="head">
<input type="text" v-model="message">
<button @click="submit"> </button>
</div>
<List :lists = "lists"/>
</div>
</template>
<script>
import List from './components/List.vue'
export default {
// 컴포넌트 선언하기
components: {
List
},
//
data() {
return {
lists: ['html', 'css'],
message: ''
}
},
//
methods: {
submit() {
if (this.message) {
this.lists.push(this.message)
this.message = ''
}
},
},
// 자식 컴포넌트에서 연산을 수정하면 부모 컴포넌트의 데이터에 영향을 줄 수 있으므로, 여기서는 수정하지 않는 것이 좋습니다.
watch:{
lists(newVal){
console.log(newVal);
}
}
}
</script>
어떤 종류의 효과를 얻고 싶으신가요? 페이지에 입력 상자가 있고 확인 버튼이 있으며 제출을 클릭하면 데이터를 데이터 소스와 동기화할 수 있으며 하위 컴포넌트가 이 데이터를 읽고 페이지에 표시할 수 있습니다.
App.vue에 List.vue라는 컴포넌트를 도입하고 페이지에 로드합니다.
컴포넌트 소개: import List from './components/List.vue' 통해 컴포넌트를 소개한 후 컴포넌트를 선언하고, { 목록 }을 통해 컴포넌트를 선언하면 컴포넌트를 가져와서 사용할 수 있습니다!
데이터 소스: 모든 데이터를 저장하기 위해 lists라는 변수가 선언되고, 데이터를 추가하기 위해 message라는 변수가 사용되며, 메시지는 양방향으로 v-모델을 사용하여 입력 상자에 동적으로 바인딩됩니다.
방법: @click을 사용하여 제출 메서드를 선언하여 확인 버튼에 클릭 이벤트를 바인딩하고, 확인 버튼을 클릭하면 입력 상자가 비어 있지 않은 경우 데이터가 목록 배열에 저장됩니다.
watch: 하위 컴포넌트가 소품의 데이터를 수정하는지 여부를 수신하는 데 사용되며, 소품의 데이터를 수정하려고 시도하는 버튼이 하위 컴포넌트에 추가되며, 데이터가 성공적으로 수정되었는지 여부를 수신하는 데 사용됩니다.
하위 컴포넌트에 값을 전달하는 방법: <List :lists = "lists"/> 컴포넌트 선언 위치에서 v-bind를 사용하여 프로퍼티를 바인딩하여 목록 배열을 하위 컴포넌트에 직접 전달합니다.
다음으로 하위 구성 요소에 대해 소개합니다.
<!-- List.vue -->
<template>
<div class="body">
<ul>
<li v-for="(item,index) in lists" :key="index">{{ item }}</li>
</ul>
<button @click="changeProps">소품 수정하기</button>
</div>
</template>
<script>
export default {
//소품에서 데이터 가져오기
props:['lists'],
//데이터 수정 시도하기
methods:{
changeProps(){
this.lists[0] = 'HTML'
}
}
}
</script>
자식 컴포넌트에서 부모 컴포넌트로부터 전달받은 데이터를 가져오고, v-for를 사용하여 페이지에 데이터를 로드하고, 소품을 수정할 수 있는 버튼을 제공하여 부모 컴포넌트로부터 전달받은 데이터를 수정하려고 시도하고, 수정 성공 여부를 확인하기 위해 부모 컴포넌트에서 watch를 사용합니다.
데이터 가져오기: 여기서는 props:['lists']를 직접 사용하여 목록이라는 이름의 데이터를 가져오고, v-for를 사용하여 li에 데이터를 로드합니다.
데이터 수정 시도: 클릭하면 목록 데이터의 데이터를 0의 첨자로 수정하여 HTML로 변환하는 버튼을 제공합니다.
효과를 보세요!
보시다시피, 자식 컴포넌트는 부모 컴포넌트에서 전달된 데이터를 읽을 뿐만 아니라 동적으로 업데이트합니다! 소품 변경을 클릭하면 페이지의 첫 번째 데이터가 HTML에서 HTML로 변경되지만, 부모 컴포넌트도 변경되었는지 확인하려면 부모 컴포넌트를 살펴보세요.
보시다시피 콘솔은 아무것도 출력하지 않습니다. 즉, 부모 컴포넌트의 데이터는 어떤 식으로도 영향을 받지 않으며, 자식 컴포넌트는 부모 컴포넌트의 데이터를 수정하지 않고 단순히 부모 컴포넌트가 이미 전달한 데이터를 수정하여 자식 컴포넌트 자체에서 가져온 데이터를 수정할 뿐입니다.
프로퍼티는 자식 컴포넌트에서만 사용할 수 있는 단방향 데이터 흐름으로, 변경해도 부모 컴포넌트가 이를 감지할 수 없기 때문에 변경하지 않는 것이 좋습니다.
공식 문서 설명
모든 프로퍼티는 단방향 바인딩 원칙을 따르며, 부모 컴포넌트의 업데이트에 따라 프로퍼티가 변경되면 새로운 상태가 역전되지 않고 자연스럽게 자식 컴포넌트로 전달됩니다. 이렇게 하면 자식 컴포넌트가 실수로 부모 컴포넌트의 상태를 수정하는 상황을 방지할 수 있으며, 그렇지 않으면 애플리케이션의 데이터 흐름이 혼란스럽고 이해하기 어려워질 수 있습니다.
또한 부모 컴포넌트가 업데이트될 때마다 모든 자식 컴포넌트의 소품이 최신 값으로 업데이트되므로 자식 컴포넌트의 소품을 변경할 필요가 없습니다.
하위 컴포넌트는 부모 컴포넌트에 값을 전달합니다.
자식 컴포넌트가 부모 컴포넌트에 값을 어떻게 전달할까요?
emit: 현재 컴포넌트에서 사용자 정의 이벤트를 트리거하는 컴포넌트에 의해 트리거되는 사용자 정의 이벤트를 선언하는 데 사용됩니다. 추가 매개변수는 이벤트 리스너의 콜백 함수에 전달됩니다. 유효성 검사 함수는 컴포넌트의 $emit 호출에 전달된 추가 인수를 받습니다. 예를 들어, this. emit('foo', 1)이 호출되면 foo에 해당하는 유효성 검사 함수가 인수를 받습니다. 유효성 검사 함수는 이벤트 매개변수가 유효성 검사를 통과했는지 여부를 나타내는 부울 값을 반환해야 합니다. 제가 직접 설명하자면, 하위 컴포넌트는 이벤트 매개변수와 함께 $emit을 통해 이벤트를 게시하고, 상위 컴포넌트는 이벤트를 구독하여 이벤트가 트리거되면 상위의 구독이 적용되도록 할 수 있습니다! 동시에 부모 컴포넌트의 구독도 매개 변수를 가져옵니다.
사용법
<!--서브 컴포넌트 헤드.vue-->
this.$emit('add',this.message)//첫 번째는 이벤트 이름, 두 번째는 값입니다.
<!--부모 컴포넌트 ->
<!-- 자식 컴포넌트가 추가 이벤트를 게시하자마자 핸들 이벤트가 발생합니다.>
<Head @add="handle"/>
테이크는 정확히 어떻게 작동하나요? 방금 설명한 사례를 가지고 약간의 수정을 가합니다:
먼저 하위 컴포넌트인 Head.vue를 소개하겠습니다.
<!-- Head.vue -->
<template>
<div>
<div class="head">
<input type="text" v-model="message">
<button @click="submit"> </button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
}
},
methods: {
submit() {
if (this.message) {
// 사용할 부모 컴포넌트에 메시지 전달하기
// 추가 이벤트 게시
this.$emit('add',this.message)//첫 번째는 이벤트 이름, 두 번째는 값입니다.
this.message = ''
}
},
}
}
</script>
여기서 입력 입력 상자가 하위 컴포넌트를 통과하고 하위 컴포넌트에 데이터가 입력된 다음 이 데이터가 상위 컴포넌트로 전달되고, 상위 컴포넌트는 이 데이터를 가져와 페이지에 로드합니다.
데이터 소스: 메시지 변수는 하위 컴포넌트 데이터 소스에 정의되며, 이 변수는 입력 입력 상자에 입력된 데이터를 v-모델을 사용하여 동적으로 바인딩합니다.
메소드: $emit을 사용하여 add라는 사용자 지정 이벤트를 게시하고 메소드 본문에서 변수 메시지가 null이 아닌 경우 메시지를 매개변수로 받아들이는 제출 메소드를 정의합니다.
확인 버튼: 이 확인 버튼에는 v-on을 사용하여 클릭 이벤트가 바인딩되어 있으며, 이 버튼을 클릭하면 제출 메서드가 트리거됩니다!
이 시점에서 자식 컴포넌트의 기능을 기본적으로 소개하고, 다음으로 부모 컴포넌트 App.vue를 소개합니다.
<!-- App.vue -->
<template>
<div>
<!-- <head /> -->
<!-- 자식 컴포넌트가 추가 이벤트를 게시하자마자 핸들 이벤트가 발생합니다.>
<Head @add="handle"/>
<div class="body">
<ul>
<li v-for="(item, index) in lists" :key="index">{{ item }}</li>
</ul>
</div>
</div>
</template>
<script>
import Head from '@/components/body2/Head.vue'
export default {
components: {
Head
},
data() {
return {
lists: ['html', 'css'],
}
},
methods:{
// 이벤트 진행
handle(val){
this.lists.push(val)
}
}
}
</script>
App.vue 페이지에서 목록 배열을 정의하면 배열의 데이터가 v-for를 사용하여 페이지에 로드되고 하위 배열에서 전달된 데이터를 가져올 수 있습니다.
데이터 소스: 데이터를 저장할 목록 배열을 정의하고 목록의 데이터를 v-for를 통해 페이지에 로드합니다.
메소드: 핸들 메소드가 정의되고 리스트 배열에 저장되는 매개변수 val을 받습니다. 부모 컴포넌트는 <Head @add="handle"/> 통해 자식 컴포넌트의 add 메소드를 구독하고, 자식 컴포넌트가 추가 메소드를 게시할 때마다, 즉 추가 메소드가 트리거될 때마다 부모 컴포넌트의 핸들 메소드가 트리거되며, 핸들 메소드의 매개 변수는 자식 컴포넌트의 $emit이 전달하는 매개 변수에서 나옵니다.
직접 와서 작동 방식을 확인하세요!
보시다시피, 자식 컴포넌트에서 부모 컴포넌트로 값을 전달하는 효과도 구현되어 있습니다!
props와 $emit을 사용하면 부모 컴포넌트의 도움을 받아 형제 컴포넌트와 통신할 수 있습니다.
위의 지식 포인트에 대해 소개 한 다음 위의 경우를 살펴보면 이번에는 부모 구성 요소 App.vue 두 하위 구성 요소 Head.vue와 List.vue가 있으며 데이터는 두 하위 구성 요소에 있었고 형제 구성 요소 통신을 달성하기 위해 부모 구성 요소에서 하위 구성 요소 값으로, 하위 구성 요소에서 부모 구성 요소 값으로, 부모 구성 요소를 중개자로 취하면 형제 구성 요소를 얻을 수 있다는 것을 이미 알고 있습니다! 두 컴포넌트 간의 통신!
<!-- App.vue -->
<template>
<div>
<Head @add="handle"/>
<List :msg="msg"/>
</div>
</template>
<script>
import Head from './components/body3/Head.vue'
import List from './components/body3/List.vue'
export default {
components:{
Head,
List
},
data(){
return {
msg:''
}
},
methods:{
handle(val){
this.msg = val
}
},
}
</script>
<!-- Head.vue -->
<template>
<div>
<div class="head">
<input type="text" v-model="message">
<button @click="submit"> </button>
</div>
</div>
</template>
<script>
export default {
data(){
return {
message:''
}
},
methods:{
submit(){
if(this.message)
{
this.$emit('add',this.message)
this.message = ''
}
}
}
}
</script>
<!-- List.vue -->
<template>
<div>
<div class="body">
<ul>
<li v-for="(item, index) in lists" :key="index">{{ item }}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
msg:{
type:String,
default:''//기본적으로 비어 있음
}
},
watch:{
msg(newVal)
{
this.lists.push(newVal)
}
},
data() {
return {
lists: ['html', 'css'],
}
},
}
</script>
세 모듈의 코드는 위와 같으며, 각 모듈은 다음에 분석됩니다:
Head.vue: Head.vue에서는 데이터 메시지를 양방향으로 v 모델을 통해 메시지를 다시 동적으로 바인딩한 다음 $emit을 사용하여 매개 변수 메시지와 함께 add라는 사용자 지정 이벤트를 게시하여 List.vue에 제출해야 합니다.
App.vue: App.vue에서 먼저 이 두 구성 요소를 도입하고 페이지에 로드하는 동시에 Head.vue의 추가 이벤트에 구독을 추가하고 추가 이벤트가 트리거되면 핸들 메서드가 실행되고 핸들 메서드는 이벤트의 매개 변수를 수락하여 데이터 소스의 데이터 msg에 할당합니다. 데이터 메시지는 :msg:"msg"를 통해 하위 배열 List에 전달됩니다.
List.vue: List.vue에서 목록 배열은 데이터 소스에서 선언되고 v-for를 통해 페이지에 로드된 다음 props:{msg:{type:String,default:''}} 통해 가져옵니다.
props: {
msg:{
type:String,
default:''//기본적으로 비어 있음
}
},
이것은 또한 객체를 통해 데이터를 가져 오는 방법을 취하는 소품입니다. 메시지는 데이터의 이름, 유형은 데이터의 유형, 기본값은 기본 데이터가 비어 있으며, 시계가 메시지를 듣는 직후, 메시지가 변경되면 메시지가 목록에 저장됩니다!
이런 식으로 형제 구성 요소의 통신이 이루어집니다! 그 효과를 보세요!
둘째, vuex 공개 저장소
위의 학습을 통해 이미 부모-자식 구성 요소 통신뿐만 아니라 형제 구성 요소의 통신을 알고 있으며, 이제 3 계층 구성 요소 또는 그 이상이 있으면 위의 방법을 사용하여 값을 전달할 수 있지만 상당히 번거로울 것입니다!
오늘은 공식적으로 패키징된 공용 리포지토리인 vuex를 소개합니다.
모든 Vuex 애플리케이션의 중심에는 기본적으로 애플리케이션의 상태 대부분을 포함하는 컨테이너인 스토어가 있으며, Vuex는 두 가지 점에서 단순한 전역 객체와 다릅니다:
- Vuex 상태 저장소는 반응형입니다. Vue 컴포넌트가 스토어에서 상태를 읽을 때 스토어의 상태가 변경되면 해당 컴포넌트는 그에 따라 효율적으로 업데이트됩니다.
- 스토어에서 직접 상태를 변경할 수 없습니다. 스토어에서 상태를 변경하는 유일한 방법은 명시적으로 변경 사항을 커밋하는 것뿐이므로 상태의 모든 변경 사항을 쉽게 추적할 수 있고 애플리케이션을 더 잘 이해하는 데 도움이 되는 도구를 구현할 수 있습니다.
나중에 다룰 새로운 버전의 피니아도 있습니다! 오늘은 vuex에 대해 알아보는 것으로 시작해 보겠습니다.
vuex 설치하기
npm 설치 방법
npm install vuex@next --save
원사 설치 방법
yarn add vuex@next --save
그 직후 src 디렉터리에 새 스토어 폴더를 생성하고 스토어에 js 구성 파일을 정의할 수 있습니다!
웨어하우스에서 데이터를 읽는 방법
이제 다시 받은 케이스가 공개 리포지토리를 통해 직접 영향을 받는다고 가정해 보세요!
먼저 구성 파일을 작성하세요! 데이터를 리포지토리에 넣고, 여기서 구성 파일은 index.js로 작성됩니다.
index.js
import { createStore } from 'vuex'
// 새 스토어 인스턴스 생성하기
const store = createStore({
state(){//데이터 소스 데이터와 동일
return {
lists:['html','css','js']
}
},
})
// 던지기 스토어
export default store
vuex의 구성 파일은 라우팅과 매우 유사하며, 먼저 vuex에서 createStore 함수를 도입한 다음 createStore의 실행 결과로 store를 정의합니다! 새 스토어 인스턴스를 생성한 다음 export default store를 사용하여 이 스토어 인스턴스를 던집니다.
createStore에 객체를 넣은 다음 상태 함수를 선언합니다.
웨어하우스 데이터 소스 상태: 각 모듈의 데이터 소스와 유사하게 객체를 반환하는 함수이며, 여기서는 웨어하우스 데이터 소스에 배열 목록을 직접 정의합니다.
List.vue로 이동
<template>
<div>
<div class="body">
<ul>
<li v-for="(item, index) in lists" :key="index">{{ item }}</li>
</ul>
</div>
</div>
</template>
<script>
// 저장소 내 데이터 소스 소개, 공식적인 방법 제공
import { mapState } from "vuex";
export default {
// 계산된 속성을 입력하면 맵스테이트가 자동으로 값을 반환합니다.
computed:mapState(['lists'])
}
</script>
list.vue에서는 공식 mapState 래퍼 메서드를 도입하여 리포지토리 데이터 소스에서 값을 읽을 수 있습니다! 리포지토리의 데이터를 동적으로 읽으려면 mapState(['lists'])를 호출하여 원하는 데이터를 가져오는 계산된 계산 속성만 있으면 되며, ['lists']는 리포지토리에서 가져오고자 하는 데이터입니다.
계산된 계산 속성이 반환 값을 원하지 않는데 여기서 직접 호출이 괜찮은 이유는 무엇인가요?
이는 맵스테이트가 자동으로 값을 반환하기 때문입니다.
웨어하우스에서 데이터를 수정하는 방법
한 가지 알아야 할 것은 Vuex의 데이터 구성 요소는 일반적으로 수정할 수 없으며 여기서는 약간의 특별한 수단, 즉웨어 하우스의 데이터는웨어 하우스 관리자 만 수정할 수 있으며 수정하려는 다른 사람은 등록을 통해 수정해야하며 임의로 수정할 수 없다는 것입니다.
Vuex에서 저장소의 상태를 변경하는 유일한 방법은 변경을 커밋하는 것입니다. Vuex의 변경은 이벤트와 매우 유사하며, 각 변경에는 문자열 이벤트 유형과 콜백 함수가 있습니다. 이 콜백 함수는 실제로 상태가 변경되는 곳이며, 첫 번째 인수로 상태를 받습니다:
리포지토리의 구성 파일 index.js로 이동하면 리포지토리에 데이터를 추가하는 메서드가 필요합니다.
index.js
import { createStore } from 'vuex'
// 새 스토어 인스턴스 생성하기
const store = createStore({
state(){//데이터 소스 데이터와 동일
return {
lists:['html','css','js']
}
},
// 리포지토리의 데이터는 리포지토리 관리자만 이동할 수 있습니다.
mutations:{//methods
// "이"를 사용하여 데이터에 액세스하여 공식 매개 변수를 수신 할 수 없으며 첫 번째 매개 변수는 정의되고 두 번째 매개 변수는 수동으로 정의 할 수 있습니다.
listsAdd(state,val){
state.lists.push(val)
}
}
})
// 던지기 스토어
export default store
구성 위에 정의된 메소드에 해당하는 변이 속성이 추가됩니다!
**돌연변이:** 돌연변이의 함수는 this를 사용할 수 없습니다. 리포지토리 데이터 소스의 데이터에 액세스하려면 기본적으로 하나의 매개 변수, 즉 첫 번째 매개 변수는 리포지토리 데이터 소스를 참조하는 state이며, 전달한 공식 매개 변수는 두 번째 매개 변수부터 시작됩니다.
웨어하우스 데이터 소스에 데이터를 추가하는 작업을 구현하기 위해 state와 val이라는 두 개의 매개 변수를 받는 listsAdd 메서드가 추가됩니다.
값 state.lists.push(val) 웨어하우스 데이터 원본에 추가됩니다.
다음으로 Head.vue 컴포넌트로 이동합니다.
Head.vue
<template>
<div>
<div class="head">
<input type="text" v-model="message">
<button @click="submit"> </button>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
data() {
return {
message: ''
}
},
methods: {
submit() {
// 스토어에 데이터를 넣는 방법
this.listsAdd(this.message)//전달된 실제 매개변수는 두 번째 공식 매개변수부터 시작해야 합니다.
},
// 디컨스트럭션을 통해 mapMutations에서 메서드 가져오기
...mapMutations(['listsAdd'])
},
}
</script>
mapMutations: vuex에서 돌연변이를 가져오는 메서드를 제공하는 공식 함수, mapMutations를 도입한 다음, 디컨스트럭션을 통해 메서드 ...mapMutations(['listsAdd']) mapMutations를 가져오고, [listsAdd]는 메서드 이름을 가져오는 메서드를 정의하고, 마지막으로 마지막으로 제출 메서드 this.listsAdd(this.message) 이 메서드를 호출하여 메시지 데이터를 리포지토리에 전달하고 리포지토리에 추가할 수 있습니다!
마지막으로 App.vue에서 컴포넌트를 로드하고 효과를 다시 확인하세요!
App.vue
<template>
<div>
<Head />
<List />
</div>
</template>
<script>
import Head from './components/body4/Head.vue'
import List from './components/body4/List.vue'
export default {
components: {
Head,
List
},
data() {
return {
}
},
methods: {
},
}
</script>
효과:
이렇게 하면 부모 컴포넌트와 자식 컴포넌트, 형제 컴포넌트 간에 데이터를 훨씬 쉽게 교환할 수 있습니다! 물론 뷰엑스에는 이보다 훨씬 더 많은 기능이 있으며, 앞으로 더 많은 학습이 이루어질 것입니다!
마지막으로
앞으로도 vue3, element-ui 및 관련 백엔드 문서를 계속 출력할 예정입니다! 함께 한 걸음 더 나아갑시다!
오늘은 여기까지입니다!
개인 Github:





