一、【props】
props通信方式是实际开发当中运用比较多的通信方式,简化 父传子,子传父
若:父传子通过属性绑定非函数方式;若:子传父通过属性绑定函数方式
1.父传子
父组件
<template>
<div class="father">
<p>我是父组件</p>
<p>
父组件接受子组件的数据:{{ }}
</p>
<Son :money="money"/>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son from './son.vue'
const money = ref(100)
</script>
<style>
.father{
width: 100%;
height: 200px;
background-color: aquamarine;
}
</style>
子组件
<template>
<div class="son">
<p>我是子组件</p>
<p>父组件给我的数据:{{ money }}</p>
</div>
</template>
<script lang="ts" setup name="Son">
defineProps(['money'])
</script>
2.子传父
父组件
<template>
<div class="father">
<p>我是父组件</p>
<p>
父组件接受子组件的数据:{{ sonMoney }}
</p>
<Son :money="money" :sonSendMoeny="getMoeny"/>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son from './son.vue'
// 父亲的钱
const money = ref(100)
// 儿子给父亲的钱
const sonMoney = ref(0)
// 父组件传递给子组件的函数
function getMoeny(value:number){
sonMoney.value = value
}
</script>
<style>
.father{
width: 100%;
height: 200px;
background-color: aquamarine;
}
</style>
子组件
<template>
<div class="son">
<p>我是子组件</p>
<p>父组件给我的数据:{{ money }}</p>
<button @click="sonSendMoeny(senFatherMoney)">儿子给父亲的钱</button>
</div>
</template>
<script lang="ts" setup name="Son">
import { ref } from 'vue'
defineProps(['money','sonSendMoeny'])
// 儿子给父亲的钱
const senFatherMoney = ref(50)
</script>
二、自定义事件子传父
父组件
<template>
<div class="father">
<p>我是父组件</p>
<p>
父组件接受子组件的数据:{{ sonMoney }}
</p>
<Son :money="money" @son-send-moeny="getMoeny"/>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son from './son.vue'
// 父亲的钱
const money = ref(100)
// 儿子给父亲的钱
const sonMoney = ref(0)
// 父组件传递给子组件的函数
function getMoeny(value:number){
sonMoney.value = value
}
</script>
<style>
.father{
width: 100%;
height: 200px;
background-color: aquamarine;
}
</style>
子组件
<template>
<div class="son">
<p>我是子组件</p>
<p>父组件给我的数据:{{ money }}</p>
<button @click="sonSendMoeny">儿子给父亲的钱</button>
</div>
</template>
<script lang="ts" setup name="Son">
import { ref } from 'vue'
defineProps(['money'])
const emit = defineEmits(['son-send-moeny'])
// 儿子给父亲的钱
const senFatherMoney = ref(50)
// 子组件触发的函数
function sonSendMoeny(){
emit('son-send-moeny',senFatherMoney)
}
</script>
三、发布订阅方式(事件总线)mitt 实现任意组件通信
mitt 的用法:
1. npm i mitt 安装miit
2.导入 调用 暴露
// 引入mitt
import mitt from 'mitt'
// 调用mitt得到emitter emitter能绑定事件 触发事件
const emitter = mitt()
// 暴露事件
export default emitter
// 用法
// emitter.on('事件名称','回调') 绑定事件
// emitter.emit('事件名称') 触发事件
// emitter.off('事件名称') 解除绑定事件
// emitter.all.clear() 解除所有绑定事件
哥哥组件
<template>
<div class="son">
<p>我是哥哥组件</p>
<p>妹妹给我的钱:{{ GirlMoney }}</p>
<button @click="giveMoeny">哥哥给妹妹的钱</button>
</div>
</template>
<script lang="ts" setup name="Son">
import { ref } from 'vue'
import emitter from '@/untils/emitter';
const money = ref(100)
// 妹妹给我钱
const GirlMoney = ref(0)
// 哥哥触发事件给妹妹钱
function giveMoeny(){
emitter.emit('gg-send-money',money)
}
// 哥哥订阅妹妹触发的事件
emitter.on('mm-send-money',(value:any)=>{
GirlMoney.value = value
})
onUnmounted(()=>{
emitter.off('mm-send-money')
})
</script>
妹妹组件
<template>
<div class="girl">
哥哥给我{{ brotherMoney }}块
</div>
<button @click="getMoeny">妹妹给哥哥钱</button>
</template>
<script lang="ts" setup name="Girl">
import { ref } from 'vue'
import emitter from '@/untils/emitter';
const money = ref(50)
const brotherMoney = ref(0)
// 妹妹订阅哥哥处触发的事件
emitter.on("gg-send-money",(value:any)=>{
brotherMoney.value = value
console.log(value)
})
// 妹妹触发事件给哥哥钱
function getMoeny(){
emitter.emit('mm-send-money',money)
}
onUnmounted(()=>{
emitter.off('gg-send-money')
})
</script>
注意:组件在卸载的时候,一定要把注册的事件卸载了
四、【$attrs】 组件通信方式
1.$attrs用于实现当前组件的父组件与孙子组件的通信(父->子->孙)
2.$attrs是一个对象,包含所有父组件的标签属性
爷爷组件
<template>
<div class="father">
<p>父亲的数据</p>
<h1>{{ a }}</h1>
<h1>{{ b }}</h1>
<h1>{{ c }}</h1>
<h1>{{ d }}</h1>
<Son :a="a" :b="b" :c="c" :d="d" :changeData="changeData"/>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son from './son.vue'
let a = ref(1)
let b = ref(2)
let c = ref(3)
let d = ref(4)
// 孙子改变爷爷的数据
function changeData(data:number){
a.value += data
b.value += data
}
</script>
<style>
.father{
width: 100%;
height: auto;
background-color: aquamarine;
padding-bottom: 30px;
}
</style>
父亲组件
<template>
<div class="son">
<Grandson v-bind="$attrs"/>
</div>
</template>
<script lant="ts" setup name="Son">
import Grandson from './grandson.vue';
</script>
孙子组件
<template>
<div class="grandson">
<p>爷爷给的数据:</p>
<h1>{{ a }}</h1>
<h1>{{ b }}</h1>
<h1>{{ c }}</h1>
<h1>{{ d }}</h1>
<button @click="changeData(2)">孙子改变爷爷的数据</button>
</div>
</template>
<script lant="ts" setup name="Son">
defineProps(['a','b','c','d','changeData'])
</script>
五 【parent】父子组件通信
1.【$refs】父组件向子组件传递数据
父组件代码
<template>
<div class="father">
<p>父亲有{{money}}块钱</p>
<son1 ref="son1"/>
<son2 ref="son2"/>
<button @click="sendSon">父亲给儿子书和玩具</button>
<button @click="senAllSon($refs)">同时操作所有儿子</button>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son1 from './son1.vue'
import Son2 from './son2.vue'
let money = ref(500)
let son1 = ref()
let son2 = ref()
function sendSon(){
son1.value.bookName = '宇宙简史'
son1.value.toyName = '灭霸'
son2.value.bookName = '红楼梦'
son2.value.bookName = '孙悟空'
}
function senAllSon(refs:{[key:string]:any}){
for(let key in refs){
refs[key].bookName = '孙子兵法'
refs[key].toyName = '猪八戒'
console.log(key)
}
}
</script>
<style>
.father{
width: 100%;
height: auto;
background-color: aquamarine;
padding-bottom: 30px;
}
</style>
子组件son1代码
<template>
<div class="son1">
son1的book:{{ bookName }}
son1的toy:{{ toyName }}
</div>
</template>
<script lant="ts" setup name="Son1">
import { ref } from 'vue'
let bookName = ref('美国近代史')
let toyName = ref('蜘蛛侠')
// 向外暴露数据
defineExpose({bookName,toyName})
</script>
子组件son2代码
<template>
<div class="son">
son2的book:{{ bookName }}
son2的toy:{{ toyName }}
</div>
</template>
<script lant="ts" setup name="Son2">
import { ref } from 'vue'
let bookName = ref('中国近代史')
let toyName = ref('奥特曼')
// 向外暴露数据
defineExpose({bookName,toyName})
</script>
1.【$parent】子组件向父组件传递数据
父组件代码
<template>
<div class="father">
<p>父亲有{{money}}块钱</p>
<son2 ref="son2"/>
</div>
</template>
<script lang="ts" setup name="Father">
import { ref } from 'vue'
import Son2 from './son2.vue'
let son2 = ref()
let money = ref(500)
// 向外暴漏数据
defineExpose({money})
</script>
<style>
.father{
width: 100%;
height: auto;
background-color: aquamarine;
padding-bottom: 30px;
}
</style>
子组件代码
<template>
<div class="son">
<button @click="senMoney($parent)">子组件向父组件给钱</button>
</div>
</template>
<script lant="ts" setup name="Son2">
import { ref } from 'vue'
function senMoney(parent){
parent.money = 5000
}
</script>
六、provide、inject隔代通信
1.祖传子代
爷爷组件代码:
<template>
<div class="father">
{{ house.name }}---{{ house.price }}
<Son />
</div>
</template>
<script lang="ts" setup name="Father">
import { ref,reactive,provide } from 'vue'
import Son from './son.vue'
let house = reactive({
name:'别墅',
price:500
})
let money = ref(1000)
provide('house',house)
</script>
<style>
.father{
width: 100%;
height: auto;
background-color: aquamarine;
padding-bottom: 30px;
}
</style>
儿子组件代码:
<template>
<div class="son">
<grandSon />
</div>
</template>
<script lant="ts" setup name="Son">
import grandSon from './grandSon.vue';
</script>
孙子组件代码:
<template>
<div class="son">
爷爷给我的房子:{{ house.name }}
</div>
</template>
<script lant="ts" setup name="Son2">
import { inject } from 'vue'
// inject 第一个参数 你要传递的数据,第二个参数 默认值
let house = inject('house',{name:'房子',price:600})
console.log(house)
</script>
2.孙子组件改变爷爷组件的数据
爷爷组件通过provide inject 传递一个函数到孙子组件 在孙子组件调用这个函数,就可以实现隔代孙子组件改变爷爷组件的数据
爷爷组件代码:
<template>
<div class="father">
{{ house.name }}---{{ house.price }}
{{ money }}
<Son />
</div>
</template>
<script lang="ts" setup name="Father">
import { ref,reactive,provide } from 'vue'
import Son from './son.vue'
let house = reactive({
name:'别墅',
price:500
})
let money = ref(1000)
function updataMoney(value:number){
money.value -= value
}
provide('house',house)
provide('updataMoney',updataMoney)
</script>
<style>
.father{
width: 100%;
height: auto;
background-color: aquamarine;
padding-bottom: 30px;
}
</style>
儿子组件代码:
<template>
<div class="son">
<grandSon />
</div>
</template>
<script lant="ts" setup name="Son">
import grandSon from './grandSon.vue';
</script>
孙子组件代码:
<template>
<div class="son">
爷爷给我的房子:{{ house.name }}
<button @click="updataMoney(6)">我花爷爷的钱</button>
</div>
</template>
<script lant="ts" setup name="Son2">
import { inject } from 'vue'
// inject 第一个参数 你要传递的数据,第二个参数 默认值
let house = inject('house',{name:'房子',price:600})
let updataMoney = inject('updataMoney',()=>{})
console.log(house)
</script>