vue2,vue3,(超全)组件之间的通讯,看这一篇文章就够了❤️

590 阅读2分钟

爷组件:Grand,父组件:Father,孙组件1:SonOne,孙组件2:SonTwo, 孙组件1孙组件2 为兄弟组件

vue2

1.父传子(传值)(props)

//父组件 Father
<template>
  <div>
    <SonOne :num="num"></SonOne>
  </div>
</template>
<script>
  data() {
    return {
      num: 1
    }
  }
</script>
//子组件 SonOne
<template>
  <div>{{ num }}</div>
</template>
<script>
  props: {
    num: {
      type: number
    }
  }
  //或者这样写
  props:["son"]
</script>

2.子传父(传值)($emit)

//父组件 Father
<template>
  <div>
    <SonOne @addNum="addNum"></SonOne>
  </div>
</template>
<script>
  data() {
    return {
      num: 1
    }
  },
  methods: {
   addNum(num) {
      this.num += num;
    }
  }
</script>
//子组件 SonOne
<template>
  <div @click="addNum">点击+1</div>
</template>
<script>
  methods: {
    addNum() {
      this.$emit('addNum',1);
    }
  }
</script>

3.父调子(调用方法)(ref)

//父组件 Father
<template>
  <div>
    <SonOne ref="sonOneRef"></SonOne>
    <button @click="sonOneAddNum">调用子组件addNum方法</button>
  </div>
</template>
<script>
  methods: {
   sonOneAddNum() {
      this.$refs.sonOneRef.addNum;
    }
  }
</script>
//子组件 SonOne
<template>
  <div>{{num}}</div>
</template>
<script>
  data() {
    return {
      num: 1
    }
  },
  methods: {
    addNum(num) {
      this.num += num;
    }
  }
</script>

4.子调父(调用方法)(this.$parent.event)

  • 尽量避免使用此方法,因为会出现两个以上父组件同时引用改子组件的场景
  • 可以用 $emit,vuex,eventBus事件总线(下面会写)方法代替
//父组件 Father
<template>
  <div>
    <SonOne></SonOne>
  </div>
</template>
<script>
data() {
    return {
      num: 1
    }
  },
  methods: {
   addNum() {
      this.num += 1;
    }
  }
</script>
//子组件 SonOne
<template>
  <div @click="callParent"></div>
</template>
<script>
  methods: {
    callParent() {
      this.$parent.event.addNum
    }
  }
</script>

5.兄弟之间传值或调用方法(传值 | 调用)(eventBus事件总线)

  • 定义模块 src/bus.js,内容就是导入Vue模块,并导出一个Vue实例对象:
//bus.js
import Vue from 'vue'
export default new Vue() 
  • 此演示是 孙组件1 SonOne孙组件2 SonTwo 发送一个事件
//孙组件1 SonOne
<template>
  <div @click="sendMsg"></div>
</template>
<script>
import bus from '@/bus.js'
  methods: {
   sendMsg() {
      bus.$emit('xxx', 'hello,world')
    }
  }
</script>
//孙组件2 SonTwo
<template>
  <div @click="callParent"></div>
<script>
  created(){
    bus.$on('xxx', data=>{ console.log(data) }) 
  }
</script>

6.爷传孙1(传值)($attrs)

//爷组件 Grand
<template>
  <Father :toSonOne="toSonOne"></Father>
</template>
<script>
data(){
  return {
    toSonOne:"爷组件传给孙组件的值!~" 
  } 
}
</script>
//孙组件 SonOne
<template>
  <div>{{toSonOne}}</div>
</template>
<script>
props:{
  toSonOne: { type: String }
}
</script>

7.爷传孙2(传值)(Provide,Inject)

//爷组件 Grand
<script>
  export defalut {
    data() {
      arr:[1,2,3]
    },
    provide() {
      return {
        name:"test",
        age:18,
        length: this.arr.legth
      }
    }
  }
</script>
//孙组件 SonOne
<template>
  <div>{{name}}-{{age}}-{{length}}</div>
</template>
<script>
  export defalut {
    inject: ["name","age","length"]
  }
</script>

8.孙传爷(传值)($listeners)

//孙组件 SonOne
<template>
  <div @click="sendToGrand">{{toGrand}}</div>
</template>
<script>
data(){
  return{
    toGrand:"孙组件传给父组件的值!~" 
  } 
},
methods:{
  sendToFather(){
     this.$emit("toGrand",this.toGrand)
  }
}
</script>
//父组件 Father
<template>
  <SonOne v-on="$listeners"></SonOne>
</template>
<script>
</script>
//爷组件 Grand
<template>
  <Father @toGrand="getFromSonOne"></Father>
</template>
<script>
methods:{
  getFromSonOne(val){
    console.log(val)
  } 
}
</script>

9.爷调孙(调用方法)(eventBus事件总线)

  • 推荐使用eventBus事件总线(第5项)

10.孙调爷(调用方法)(eventBus事件总线 | $listeners)

  • 推荐使用eventBus事件总线(第5项) 或 $listeners(第8项)

vue3(常规语法)

1.父传子(传值)(props)

//父组件 Father
<template>
    <SonOne :num="num"></SonOne>
</template>
<script>
  import {ref} from 'vue'
  setup () {
    const num = ref(1)
    return {num}
  }
</script>
//子组件 SonOne
<template>
  <div>{{ num }}</div>
</template>
<script>
  props: ['num'],
</script>

2.子传父(传值)(emit)

//父组件 Father
<template>
    <SonOne @sonHandler="sonHandler"></SonOne>
</template>
<script>
  import {ref} from 'vue'
  setup () {
    function sonHandler () {         
    }
    return { fn } 
  }
</script>
//子组件 SonOne
<template>
</template>
<script>
  emits:['sonHandler']
  setup (props, context) {
    function fn () {         
      context.emit('sonHandler', '这是子组件传给父组件的') }
    }
    return { fn } 
  }
</script>

3.父调子(调用方法)(ref)

  • 看vue3(语法糖的3)

4.子调父(调用方法)(emit)

  • 看vue3(语法糖的4)

5.爷传孙(传值)(Provide,Inject)

  • 看vue2的(7)

6.其他组件传值请用最后写的mitt库

vue3(语法糖setup)

1.父传子(传值)(props)

//父组件 Father
<template>
    <SonOne :num="num"></SonOne>
</template>
<script setup>
import {ref} from 'vue'
const num = ref(1)
</script>
//子组件 SonOne
<template>
  <div>{{ num }}</div>
</template>
<script setup>
const props = defineProps({
  num: {
    type: number
  }
})
</script>

2.子传父(传值)(emit)

//父组件 Father
<template>
    <SonOne @sendMsg="sendMsg"></SonOne>
</template>
<script setup>
  function sendMsg(msg) {
    console.log(msg);
  }
</script>
//子组件 SonOne
<template>
  <div @click="sendMsgClick"></div>
</template>
<script setup>  
  const emit = defineEmits(['sendMsg'])
  function sendMsgClick() {
    emit('sendMsg', 'hello');
  }
</script>

3.父调子(调用方法)(ref)

  • 子组件要defineExpose导出
//父组件 Father
<template>
    <SonOne ref="sonOneRef"></SonOne>
</template>
<script setup>
  import {ref} from 'vue'
  const sonOneRef = ref()
  function addNum(msg) {
    sonOneRef.value.addNum
    console.log('获取子组件中的num', sonOneRef.value.num );
  }
</script>
//子组件 SonOne
<template>
  <div>{{num}}</div>
</template>
<script setup>  
  import {ref} from 'vue'
  const num = ref(1) 
  function addNum(count) {
    num.value += count
  }
  defineExpose({num,addNum})
</script>

4.子调父(调用方法)(emit)

//父组件 Father
<template>
    <SonOne @fatherAlert="fatherAlert"></SonOne>
</template>
<script setup>
  function fatherAlert(msg) {
    alert('我是爸爸的方法')
  }
</script>
//子组件 SonOne
<template>
  <div @click="clickChild"></div>
</template>
<script setup>  
  const emit = defineEmits(['fatherAlert'])
  function clickChild() {
    emit('fatherAlert');
  }
</script>

5.爷传孙(传值)(Provide,Inject)

  • 看vue2的(7)

6.其他组件传值请用最后写的mitt库

vue其他组件通信(mitt.js)(vue2,vue3都可以用)

  1. npm install mitt
  2. 在utils文件夹里创建eventbus.js文件
//eventbus.js
import mitt from "mitt"
const emitter = mitt()
export default emitter
  1. 发送事件
<template>
  <button @click="btnClick"></button>
</template>
<script>
import emitter from "@/utils/eventbus.js"
export default {
  methods:{
    btnClick() {
      emitter.emit("add",2)
    }
  }
}
</script>
  1. 接受事件
<script>
import emitter from "@/utils/eventbus.js"
export default {
  created(){
    emitter.on("add",() => {...})
  }
}
</script>
  1. 接受全部事件
<script>
import emitter from "@/utils/eventbus.js"
export default {
  created(){
    emitter.on("*",(type,info) => {
      //type: 传的事件名称
      //info: 传的值
    })
  }
}
</script>
  1. 取消监听 emitter.all.clear()