Vue3组件之间的通信方式

props

实现了父组件给子组件传值

  • 父组件
<template>
    <div class="box">
        <h1>父组件</h1>  
        <hr>  
    <Child info="测试" :momeny="momeny"></Child>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const momeny=ref(100)
import Child from './Child.vue';
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
}
    </style>

  • 子组件
<template>
   <div class="te">
    子组件
    <br>
    {{ info }}
    <br>
    {{ momeny }}
   </div>
</template>

<script setup lang="ts">
import { PropType } from "vue";
// 需要使用到defineProps方法去接受父组件传递过来的数据
// PropType 校验数据类型
// 
const props = defineProps({
  info: {
    //  required 字段是否必传
    required: true,
    type: String as PropType<String>,
    default: "",
  },
  momeny: {
    required: true,
    type: Number as PropType<Number>,
    default:0,
  },
  IsA: {
    required: false,
    type: Boolean as PropType<Boolean>,
    default:true,
  }
});
</script>

<style lang="scss" scoped>
.te{
    width: 400px;
    height: 200px;
    background-color: rgb(218, 195, 26);
}
</style>

自定义事件

实现了 子组件给父组件传值

  • 父组件
<template>
    <div class="box">
        <h1>父组件</h1>  
        <hr>  
        <EventChile @handle="handle" @click="handleClick"/>
    </div>
    
</template>

<script setup lang="ts">
import EventChile from './EventChile.vue'
const handle=(parms1,parm2)=>{
    console.log(parms1,parm2)
}
const handleClick=(parms1,parm2)=>{
    console.log(parms1,parm2)
}
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
}
</style>

  • 子组件
<template>
    子组件
    <br>
    <button @click="handleClick">点击触发自定义事件</button>
    <button @click="$emit('click','测试1',100)">点击触发</button>
</template>

<script setup lang="ts">
// 利用defineEmits 方法返回函数触发自定义事件
const $emit=defineEmits(['handle','click'])
const handleClick=()=>{
    // 第一个参数事件类型,第二个 或者N个 参数为注入参数
    $emit('handle','测试',100)
}

</script>

<style lang="scss" scoped></style>

全局事件总线

实现跨组件传值

  • 添加mitt
cnpm i mitt
  • 添加mitt
import mitt from 'mitt';
const $bus=mitt();

export default $bus;
  • 父组件
<template>
    <div class="box">
        <h1>父组件</h1>  
        <hr>  
        <div class="box-child">
            <EventChild/>
            <EventChild1/>
        </div>
    </div>
</template>

<script setup lang="ts">
import EventChild from './EventChild.vue'
import EventChild1 from './EventChild1.vue'
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
    .box-child{
        display: flex;
        justify-content: space-between;

    }
}
    </style>

  • 子组件1
<template>
    <div class="child">
        子组件
        <br>
        接受到的元素
        {{ text }}
        {{ memeny }}
    </div>
</template>

<script setup lang="ts">
import $bus from '../../bus';
import {ref} from 'vue'
const text=ref('')
const memeny=ref(0)
$bus.on('car',(car)=>{
    text.value=car.text
    memeny.value=car.memeny
})
</script>

<style lang="scss" scoped>
.child{
    width: 300px;
    height: 300px;
    background-color: yellow;
}
</style>

  • 子组件2
<template>
    <div class="child">
        子组件
        <br>
        <button @click="handleClick">点击给另一个子组件传值</button>
    </div>
</template>

<script setup lang="ts">
import $bus from '../../bus';
const handleClick=()=>{
    $bus.emit('car',{
        text:'测试',
        memeny:100
    })
}
</script>

<style lang="scss" scoped>
.child{
    width: 300px;
    height: 300px;
    background-color: yellowgreen;
}
</style>

v-model

  • 父组件
<template>
    <div class="box">
        <h1>父组件{{ momeny }}</h1>  
        <hr>  
      <ModelChild  v-model:momeny="momeny" ></ModelChild>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const momeny=ref(100)
import ModelChild from './ModelChild.vue';

</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
}
    </style>

  • 子组件
<template>
  子组件
  <br />
  {{ momeny }}
  <button @click="handleAdd">添加</button>
</template>

<script setup lang="ts">
import { PropType } from "vue";
const $emit = defineEmits(["update:momeny"]);
const props = defineProps({
  momeny: {
    required: true,
    type: Number as PropType<Number>,
    default: 0,
  },
});
const handleAdd = () => {
  $emit("update:momeny", props.momeny + 100);
};
</script>

<style lang="scss" scoped></style>

useAttrs

-父组件

<template>
    <div class="box">
        <h1>父组件</h1>  
        <hr>  
    <Child info="测试" :momeny="momeny" @click="handle"></Child>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const momeny=ref(100)
import Child from './Child.vue';
const handle=()=>{
    console.log(111)
}
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
}
    </style>

  • 子组件
<template>
    子组件
    {{ atts.info  }}
    {{ atts.momeny  }}
</template>

<script setup lang="ts">
import { useAttrs } from 'vue';
const atts= useAttrs()
console.log(atts)
</script>

<style lang="scss" scoped></style>

provide 和inject

  • 父组件
<template>
    <div class="box">
        <h1>父组件  {{ car }}</h1>  
        <hr>  
    <Child></Child>
    </div>
</template>

<script setup lang="ts">
import {ref,provide} from 'vue'
import Child from './Child.vue';
const car=ref('汽车')
// vue3 提供了provide(提供) 与inject(注入),可以实现隔辈组件传递数据
// 两个参数 :
//      1.第一个参数就是提供的数据的key
//      2.第二个参数就是需要提供的数据
provide("TOKEN",car)
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
}
    </style>

  • 子组件
<template>
    <div class="box2">
        子组件
        <hr>
        <Grandson />
    </div>
</template>

<script setup lang="ts">
import Grandson from './Grandson.vue';
</script>

<style lang="scss" scoped>
.box2 {
    width: 100vw;
    height: 300px;
    background-color: rgb(24, 15, 195);
    color: #FFF;
}
</style>


  • 孙子组件
<template>
    <div class="box1">
        孙子组件
        {{ car }}
    </div>
</template>

<script setup lang="ts">
// 注入祖先组件提供数据
import {inject} from 'vue'
// 需要参数: 提供者的数据的Key
const car=inject('TOKEN')
</script>

<style lang="scss" scoped>
.box1{
    width: 100vw;
    height: 100px;
    background-color: rgb(213, 5, 137);
}
</style>

ref和$parent

  • 父组件
<template>
    <div class="box">
        <h1>父组件:{{ money }}</h1>  
        <button @click="handleClcik">找子组件借钱</button>
        <hr>  
        <div class="box_child">
            <Son ref="son"/>
            <Do/>
        </div>
    </div>
</template>

<script setup lang="ts">
// ref:可以获取真实的DOM节点,可以获取到子组件实例VC
// $parent:可以在子组件内部获取到父组件的实例
import {ref} from 'vue'
import Son from './Son.vue'
import Do from './Do.vue'
const money=ref(1000)
const son= ref()
const handleClcik=()=>{
    money.value+=10
    son.value.money-=10
    son.value.handleCL()
}

// 组件内部数据对外关闭的,别人不能访问
// 如果想让外部访问需要通过defineExpose方法对外暴露
defineExpose({
    money,
})
</script>

<style lang="scss" scoped>
.box{
    width: 100vw;
    height: 400px;
    background-color: aquamarine;
    .box_child{
        display: flex;
    }
}
    </style>

  • 子组件1
<template>
    <div class="box1">
        <h1>子组件:{{ money }}</h1>  
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const money=ref(500)

const handleCL=()=>{
    console.log('子组件方法')
}
// 组件内部数据对外关闭的,别人不能访问
// 如果想让外部访问需要通过defineExpose方法对外暴露
defineExpose({
    money,
    handleCL
})
</script>

<style lang="scss" scoped>
.box1{
    width: 100vw;
    height: 300px;
    background-color: rgb(12, 107, 185);
}
    </style>

  • 子组件2
<template>
    <div class="box1">
        <h1>子组件:{{ money }}</h1>  
        <button @click="handleClickD($parent)">想父组件借钱</button>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const money=ref(200)
const handleClickD=($parent)=>{
    console.log(parent)
    money.value+=20
    $parent.money-=20
}

</script>

<style lang="scss" scoped>
.box1{
    width: 100vw;
    height: 300px;
    background-color: rgb(150, 16, 128);
}
    </style>

pinia

插槽

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MW0309

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值