>  기사  >  웹 프론트엔드  >  구성 요소 간 통신 방법은 무엇입니까? Vue 컴포넌트 통신 방법 목록(수집할 가치가 있음)

구성 요소 간 통신 방법은 무엇입니까? Vue 컴포넌트 통신 방법 목록(수집할 가치가 있음)

青灯夜游
青灯夜游앞으로
2022-08-19 20:04:021351검색

Vue구성요소 간 통신 방법은 무엇인가요? 이 기사는 Vue2 및 Vue3의 10가지 구성 요소 통신 방법을 살펴봅니다. 모든 사람에게 도움이 되기를 바랍니다.

구성 요소 간 통신 방법은 무엇입니까? Vue 컴포넌트 통신 방법 목록(수집할 가치가 있음)

Vue에는 컴포넌트 통신 방법이 많이 있으며, Vue2와 Vue3의 구현에는 많은 차이점이 있습니다. 이 글에서는 选项式API 组合式API以及setup세 가지 구현 방법을 통해 Vue2와 Vue3의 컴포넌트 통신 방법을 종합적으로 소개합니다. 구현될 통신 방식은 아래 표와 같습니다. (학습 영상 공유: vue 영상 튜토리얼)

제공 injectNone없음expose&refmitt
method Vue2 Vue3
아버지가 아들에게 props props
아들에서 아버지로 $emit ㅋㅋㅋ 아들 제공
아들에서 상위로 inject
하위 구성 요소가 상위 구성 요소에 액세스 $parent
상위 구성 요소가 하위 구성 요소에 액세스 $children
부모님 컴포넌트 하위 컴포넌트에 액세스 $ref
Brotherly 전달된 값 EventBus

props

props는 컴포넌트 통신에서 가장 일반적으로 사용되는 통신 방법 중 하나입니다. 상위 구성 요소는 v-bind를 통해 전달되고 하위 구성 요소는 props를 통해 수신됩니다. 다음은 세 가지 구현 방법입니다

  • Optional API
//父组件

<template>
  <div>
    <Child :msg="parentMsg" />
  </div>
</template>
<script>
import Child from './Child'
export default {
  components:{
    Child
  },
  data() {
    return {
      parentMsg: '父组件信息'
    }
  }
}
</script>


//子组件

<template>
  <div>
    {{msg}}
  </div>
</template>
<script>
export default {
  props:['msg']
}
</script>
  • Combined API
//父组件

<template>
  <div>
    <Child :msg="parentMsg" />
  </div>
</template>
<script>
import { ref,defineComponent } from 'vue'
import Child from './Child.vue'
export default defineComponent({
  components:{
    Child
  },
  setup() {
    const parentMsg = ref('父组件信息')
    return {
      parentMsg
    };
  },
});
</script>

//子组件

<template>
    <div>
        {{ parentMsg }}
    </div>
</template>
<script>
import { defineComponent,toRef } from "vue";
export default defineComponent({
    props: ["msg"],// 如果这行不写,下面就接收不到
    setup(props) {
        console.log(props.msg) //父组件信息
        let parentMsg = toRef(props, 'msg')
        return {
            parentMsg
        };
    },
});
</script>
  • 설정 구문 설탕
//父组件

<template>
  <div>
    <Child :msg="parentMsg" />
  </div>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const parentMsg = ref('父组件信息')
</script>

//子组件

<template>
    <div>
        {{ parentMsg }}
    </div>
</template>
<script setup>
import { toRef, defineProps } from "vue";
const props = defineProps(["msg"]);
console.log(props.msg) //父组件信息
let parentMsg = toRef(props, 'msg')
</script>

참고

props의 데이터 흐름은 단일 항목입니다. 즉, 하위 구성 요소는 상위 구성 요소가 전달한 값을 변경할 수 없습니다.

결합된 API에서 하위 구성 요소의 다른 변수를 사용하여 수신하려는 경우 props의 값을 변경하려면 toRef를 사용해야 합니다. 속성을 반응형으로 변환하세요.

emit

하위 구성 요소는 이벤트를 게시하고 내보내기를 통해 일부 매개변수를 전달할 수 있으며, 상위 구성 요소는 v-on

  • Optional API
//父组件

<template>
  <div>
    <Child @sendMsg="getFromChild" />
  </div>
</template>
<script>
import Child from './Child'
export default {
  components:{
    Child
  },
  methods: {
    getFromChild(val) {
      console.log(val) //我是子组件数据
    }
  }
}
</script>

// 子组件

<template>
  <div>
    <button @click="sendFun">send</button>
  </div>
</template>
<script>
export default {
  methods:{
    sendFun(){
      this.$emit('sendMsg','我是子组件数据')
    }
  }
}
</script>
  • Combined API
//父组件

<template>
  <div>
    <Child @sendMsg="getFromChild" />
  </div>
</template>
<script>
import Child from './Child'
import { defineComponent } from "vue";
export default defineComponent({
  components: {
    Child
  },
  setup() {
    const getFromChild = (val) => {
      console.log(val) //我是子组件数据
    }
    return {
      getFromChild
    };
  },
});
</script>

//子组件

<template>
    <div>
        <button @click="sendFun">send</button>
    </div>
</template>

<script>
import { defineComponent } from "vue";
export default defineComponent({
    emits: ['sendMsg'],
    setup(props, ctx) {
        const sendFun = () => {
            ctx.emit('sendMsg', '我是子组件数据')
        }
        return {
            sendFun
        };
    },
});
</script>
  • 설정을 통해 이 이벤트를 모니터링합니다. 구문 설탕
//父组件

<template>
  <div>
    <Child @sendMsg="getFromChild" />
  </div>
</template>
<script setup>
import Child from './Child'
const getFromChild = (val) => {
      console.log(val) //我是子组件数据
    }
</script>

//子组件

<template>
    <div>
        <button @click="sendFun">send</button>
    </div>
</template>
<script setup>
import { defineEmits } from "vue";
const emits = defineEmits(['sendMsg'])
const sendFun = () => {
    emits('sendMsg', '我是子组件数据')
}
</script>

attrs 및 리스너

하위 구성 요소는 $attrs를 사용하여 props에 의해 전달된 속성과 속성 바인딩 속성(클래스 및 스타일)을 제외한 상위 구성 요소의 모든 속성을 가져옵니다.

하위 구성 요소는 $listeners를 사용하여 Vue3에서 더 이상 사용되지 않는 상위 구성 요소(.native 수정자 제외)의 모든 v-on 이벤트 리스너를 가져오지만 Vue3의 attrs는 상위 구성 요소가 전달한 속성만 얻을 수 있는 것은 아닙니다. 구성요소 상위 구성요소 v-on 이벤트 리스너를 가져올 수도 있습니다

  • Optional API
//父组件

<template>
  <div>
    <Child @parentFun="parentFun" :msg1="msg1" :msg2="msg2"  />
  </div>
</template>
<script>
import Child from './Child'
export default {
  components:{
    Child
  },
  data(){
    return {
      msg1:'子组件msg1',
      msg2:'子组件msg2'
    }
  },
  methods: {
    parentFun(val) {
      console.log(`父组件方法被调用,获得子组件传值:${val}`)
    }
  }
}
</script>

//子组件

<template>
  <div>
    <button @click="getParentFun">调用父组件方法</button>
  </div>
</template>
<script>
export default {
  methods:{
    getParentFun(){
      this.$listeners.parentFun('我是子组件数据')
    }
  },
  created(){
    //获取父组件中所有绑定属性
    console.log(this.$attrs)  //{"msg1": "子组件msg1","msg2": "子组件msg2"}
    //获取父组件中所有绑定方法    
    console.log(this.$listeners) //{parentFun:f}
  }
}
</script>
  • Combined API
//父组件

<template>
  <div>
    <Child @parentFun="parentFun" :msg1="msg1" :msg2="msg2" />
  </div>
</template>
<script>
import Child from './Child'
import { defineComponent,ref } from "vue";
export default defineComponent({
  components: {
    Child
  },
  setup() {
    const msg1 = ref('子组件msg1')
    const msg2 = ref('子组件msg2')
    const parentFun = (val) => {
      console.log(`父组件方法被调用,获得子组件传值:${val}`)
    }
    return {
      parentFun,
      msg1,
      msg2
    };
  },
});
</script>

//子组件

<template>
    <div>
        <button @click="getParentFun">调用父组件方法</button>
    </div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
    emits: ['sendMsg'],
    setup(props, ctx) {
        //获取父组件方法和事件
        console.log(ctx.attrs) //Proxy {"msg1": "子组件msg1","msg2": "子组件msg2"}
        const getParentFun = () => {
            //调用父组件方法
            ctx.attrs.onParentFun('我是子组件数据')
        }
        return {
            getParentFun
        };
    },
});
</script>
  • setup 구문 sugar
//父组件

<template>
  <div>
    <Child @parentFun="parentFun" :msg1="msg1" :msg2="msg2" />
  </div>
</template>
<script setup>
import Child from './Child'
import { ref } from "vue";
const msg1 = ref('子组件msg1')
const msg2 = ref('子组件msg2')
const parentFun = (val) => {
  console.log(`父组件方法被调用,获得子组件传值:${val}`)
}
</script>

//子组件

<template>
    <div>
        <button @click="getParentFun">调用父组件方法</button>
    </div>
</template>
<script setup>
import { useAttrs } from "vue";

const attrs = useAttrs()
//获取父组件方法和事件
console.log(attrs) //Proxy {"msg1": "子组件msg1","msg2": "子组件msg2"}
const getParentFun = () => {
    //调用父组件方法
    attrs.onParentFun('我是子组件数据')
}
</script>

Note

attrs를 사용하여 상위 구성요소 메소드 호출 Vue3에서 메소드 앞에 추가해야 하는 경우, 예를 들어 parentFun->onParentFun

provide/inject

provide:는 객체이거나 객체를 반환하는 함수입니다. 여기에는 미래 세대에게 물려줄 속성이 담겨 있습니다

inject: 문자열 배열 또는 객체. inject

  • Optional API
//父组件
<script>
import Child from './Child'
export default {
  components: {
    Child
  },
  data() {
    return {
      msg1: '子组件msg1',
      msg2: '子组件msg2'
    }
  },
  provide() {
    return {
      msg1: this.msg1,
      msg2: this.msg2
    }
  }
}
</script>

//子组件

<script>
export default {
  inject:['msg1','msg2'],
  created(){
    //获取高层级提供的属性
    console.log(this.msg1) //子组件msg1
    console.log(this.msg2) //子组件msg2
  }
}
</script>
  • Combined API
//父组件

<script>
import Child from './Child'
import { ref, defineComponent,provide } from "vue";
export default defineComponent({
  components:{
    Child
  },
  setup() {
    const msg1 = ref('子组件msg1')
    const msg2 = ref('子组件msg2')
    provide("msg1", msg1)
    provide("msg2", msg2)
    return {
      
    }
  },
});
</script>

//子组件

<template>
    <div>
        <button @click="getParentFun">调用父组件方法</button>
    </div>
</template>
<script>
import { inject, defineComponent } from "vue";
export default defineComponent({
    setup() {
        console.log(inject('msg1').value) //子组件msg1
        console.log(inject('msg2').value) //子组件msg2
    },
});
</script>
  • setup Syntax sugar
//父组件
<script setup>
import Child from './Child'
import { ref,provide } from "vue";
const msg1 = ref('子组件msg1')
const msg2 = ref('子组件msg2')
provide("msg1",msg1)
provide("msg2",msg2)
</script>

//子组件

<script setup>
import { inject } from "vue";
console.log(inject('msg1').value) //子组件msg1
console.log(inject('msg2').value) //子组件msg2
</script>

를 통해 상위 구성 요소 또는 상위 구성 요소에서 제공하는 값을 가져옵니다. :

provide/inject는 일반적으로 깊은 구성 요소 중첩에 사용하기에 적합합니다. 일반적으로 컴포넌트 개발에 사용됩니다.

parent/children

$parent: 자식 컴포넌트는 부모 컴포넌트의 Vue 인스턴스를 획득하고, 부모 컴포넌트의 속성 메서드 등을 획득할 수 있습니다.

$children: 부모 컴포넌트는 부모 컴포넌트의 Vue 인스턴스를 획득합니다. 직계 자식의 배열 및 모음인 자식 구성 요소. 그러나 자식 구성 요소의 순서는 보장되지 않습니다.

  • Vue2
import Child from './Child'
export default {
  components: {
    Child
  },
  created(){
    console.log(this.$children) //[Child实例]
    console.log(this.$parent)//父组件实例
  }
}

Note부모가 얻은 $children 구성 요소가 응답하지 않습니다$children并不是响应式的

expose&ref

$refs可以直接获取元素属性,同时也可以直接获取子组件实例

  • 选项式API
//父组件

<template>
  <div>
    <Child ref="child" />
  </div>
</template>
<script>
import Child from './Child'
export default {
  components: {
    Child
  },
  mounted(){
    //获取子组件属性
    console.log(this.$refs.child.msg) //子组件元素

    //调用子组件方法
    this.$refs.child.childFun('父组件信息')
  }
}
</script>

//子组件 

<template>
  <div>
    <div></div>
  </div>
</template>
<script>
export default {
  data(){
    return {
      msg:'子组件元素'
    }
  },
  methods:{
    childFun(val){
      console.log(`子组件方法被调用,值${val}`)
    }
  }
}
</script>
  • 组合式API
//父组件

<template>
  <div>
    <Child ref="child" />
  </div>
</template>
<script>
import Child from './Child'
import { ref, defineComponent, onMounted } from "vue";
export default defineComponent({
  components: {
    Child
  },

  setup() {
    const child = ref() //注意命名需要和template中ref对应
    onMounted(() => {
      //获取子组件属性
      console.log(child.value.msg) //子组件元素

      //调用子组件方法
      child.value.childFun('父组件信息')
    })
    return {
      child //必须return出去 否则获取不到实例
    }
  },
});
</script>

//子组件

<template>
    <div>
    </div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
    setup() {
        const msg = ref('子组件元素')
        const childFun = (val) => {
            console.log(`子组件方法被调用,值${val}`)
        }
        return {
            msg,
            childFun
        }
    },
});
</script>
  • setup语法糖
//父组件

<template>
  <div>
    <Child ref="child" />
  </div>
</template>
<script setup>
import Child from './Child'
import { ref, onMounted } from "vue";
const child = ref() //注意命名需要和template中ref对应
onMounted(() => {
  //获取子组件属性
  console.log(child.value.msg) //子组件元素

  //调用子组件方法
  child.value.childFun('父组件信息')
})
</script>

//子组件

<template>
    <div>
    </div>
</template>
<script setup>
import { ref,defineExpose } from "vue";
const msg = ref('子组件元素')
const childFun = (val) => {
    console.log(`子组件方法被调用,值${val}`)
}
//必须暴露出去父组件才会获取到
defineExpose({
    childFun,
    msg
})
</script>

注意

通过ref获取子组件实例必须在页面挂载完成后才能获取。

在使用setup语法糖时候,子组件必须元素或方法暴露出去父组件才能获取到

EventBus/mitt

兄弟组件通信可以通过一个事件中心EventBus实现,既新建一个Vue实例来进行事件的监听,触发和销毁。

在Vue3中没有了EventBus兄弟组件通信,但是现在有了一个替代的方案mitt.js,原理还是 EventBus

  • 选项式API
//组件1
<template>
  <div>
    <button @click="sendMsg">传值</button>
  </div>
</template>
<script>
import Bus from './bus.js'
export default {
  data(){
    return {
      msg:'子组件元素'
    }
  },
  methods:{
    sendMsg(){
      Bus.$emit('sendMsg','兄弟的值')
    }
  }
}
</script>

//组件2

<template>
  <div>
    组件2
  </div>
</template>
<script>
import Bus from './bus.js'
export default {
  created(){
   Bus.$on('sendMsg',(val)=>{
    console.log(val);//兄弟的值
   })
  }
}
</script>

//bus.js

import Vue from "vue"
export default new Vue()
  • 组合式API

首先安装mitt

npm i mitt -S

然后像Vue2中bus.js一样新建mitt.js

expose&ref

    $refs는 요소 속성을 직접 얻을 수 있으며 하위 구성 요소 인스턴스도 직접 얻을 수 있습니다
옵션 API

import mitt from 'mitt'
const Mitt = mitt()
export default Mitt

Combined API

//组件1
<template>
     <button @click="sendMsg">传值</button>
</template>
<script>
import { defineComponent } from "vue";
import Mitt from './mitt.js'
export default defineComponent({
    setup() {
        const sendMsg = () => {
            Mitt.emit('sendMsg','兄弟的值')
        }
        return {
           sendMsg
        }
    },
});
</script>

//组件2
<template>
  <div>
    组件2
  </div>
</template>
<script>
import { defineComponent, onUnmounted } from "vue";
import Mitt from './mitt.js'
export default defineComponent({
  setup() {
    const getMsg = (val) => {
      console.log(val);//兄弟的值
    }
    Mitt.on('sendMsg', getMsg)
    onUnmounted(() => {
      //组件销毁 移除监听
      Mitt.off('sendMsg', getMsg)
    })

  },
});
</script>

setup 구문 sugar

//组件1

<template>
    <button @click="sendMsg">传值</button>
</template>
<script setup>
import Mitt from './mitt.js'
const sendMsg = () => {
    Mitt.emit('sendMsg', '兄弟的值')
}
</script>

//组件2

<template>
  <div>
    组件2
  </div>
</template>
<script setup>
import { onUnmounted } from "vue";
import Mitt from './mitt.js'
const getMsg = (val) => {
  console.log(val);//兄弟的值
}
Mitt.on('sendMsg', getMsg)
onUnmounted(() => {
  //组件销毁 移除监听
  Mitt.off('sendMsg', getMsg)
})
</script>
참고로

🎜ref를 통해 하위 구성 요소 인스턴스를 얻으려면 페이지가 마운트된 후에 얻어야 합니다. 🎜🎜설정 구문 설탕을 사용할 때 하위 구성 요소는 이를 얻기 위해 요소 또는 메소드를 상위 구성 요소에 노출해야 합니다.🎜

🎜EventBus/mitt🎜🎜🎜자매 구성 요소는 다음을 통해 통신할 수 있습니다. 이벤트 센터 EventBus 구현은 이벤트를 모니터링, 트리거 및 삭제하기 위한 새로운 Vue 인스턴스를 생성합니다. 🎜🎜Vue3에는 EventBus 형제 구성 요소 통신이 없지만 이제 대체 솔루션 mitt.js가 있습니다. 원칙은 여전히 ​​EventBus🎜🎜🎜Optional API🎜🎜rrreee🎜🎜Combined API🎜🎜 🎜입니다. 먼저 mitt🎜rrreee🎜를 설치한 다음 Vue2🎜🎜mitt.js🎜rrreeerrreee🎜🎜setup 구문 sugar🎜🎜rrreee🎜에서 bus.js와 같은 새 mitt.js 파일을 만듭니다. 🎜마지막에 작성🎜🎜🎜사실 컴포넌트는 Vuex 또는 Pinia 상태 관리 도구와도 통신할 수 있습니다(그러나 이는 컴포넌트를 재사용할 수 없는 문제가 발생하므로 일반적으로 컴포넌트 간의 통신에는 권장되지 않습니다). Vuex와 Pinia의 사용법은 이 글을 참고하세요🎜Pinia와 Vuex를 분석한 글🎜🎜🎜 (학습 영상 공유: 🎜웹 프론트엔드 개발🎜, 🎜기본 프로그래밍 영상🎜)🎜

위 내용은 구성 요소 간 통신 방법은 무엇입니까? Vue 컴포넌트 통신 방법 목록(수집할 가치가 있음)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제