当前位置:   article > 正文

vue3组件通信详解

vue3组件通信

vue3组件通信方式有以下几种:porps,$emit, bus,v-model,useAttrs,$ref/$parent,provide/inject,pinia,slot。下面将逐一讲解。

  

目录

1.porps:实现父子组件通信,子组件接收的数据还是只读 

2.$emit

3.全局事件总线 $bus,使用mitt

4.v-model传值

5. $attrs/useAttrs:获取组件标签身上属性与事件

6.$ref/$parent

7.provide/inject

8.pinia :vuex:集中管理状态容器,可以实现任意组件之间的通信

9.slot 插槽分为默认插槽、具名插槽、作用域插槽(可以传递数据的插槽,子组件可以将数据回传给父组件的插槽)


 

1.porps:实现父子组件通信,子组件接收的数据还是只读

父组件中,引入子组件并给子组件绑定一个money参数

  1. <template>
  2. <div id="app">
  3. <h1>父组件</h1>
  4. <h3>富一代资产{{ money }}元</h3>
  5. <index1 :money="money"></index1>
  6. </div>
  7. </template>
  8. <script lang="ts" setup>
  9. import index1 from './view/index.vue'
  10. import { ref } from 'vue'
  11. let money = ref(1000000000000)
  12. </script>
  13. <style scoped>
  14. #app {
  15. width: 100vw;
  16. height: 100vh;
  17. color: #000;
  18. padding: 50px;
  19. box-sizing: border-box;
  20. }
  21. </style>

子组件中,使用defineProps接收,在template中,可以直接使用money,

  1. <template>
  2. <div class="index1">
  3. <h1>子组件1</h1>
  4. <h3>儿子不知道父亲有{{ porps.money }}元</h3>
  5. <h3>
  6. 儿子知道了会争这{{ money }}元(template中可以直接省略porps---script中无法省略!)
  7. </h3>
  8. </div>
  9. </template>
  10. <script setup lang="ts">
  11. import { ref } from 'vue'
  12. // porps:实现父子组件通信,props数据还是只读
  13. // 组合式api 使用 defineProps 接收父子组件传递过来的数据,可以是数组也可以是对象,
  14. //不需要引入 template中可直接使用
  15. const porps = defineProps(['money'])
  16. console.log(porps)
  17. </script>
  18. <style lang="scss" scoped>
  19. .index1 {
  20. background-color: azure;
  21. padding: 12px;
  22. }
  23. </style>

示例

2.$emit

说到$emit就要说一下自定义事件,在vue框架中事件分为两种:一种是原生的DOM事件,另外一种自定义事件。原生DOM事件可以让用户与网页进行交互,比如click、dbdlick、change、mouseenter、mouseleave...自定义事件可以实现子组件给父组件传递数据。vue2中的@click绑定的是自定义事件 ,可以通过.native修饰符变为原生DOM事件 。vue3中绑定的是原生事件,利用defineEmits方法返回函数触发自定义事件,不需要引入,直接使用。

父组件

  1. <template>
  2. <div id="app">
  3. <h1>父组件</h1>
  4. <h3>富一代资产{{ money }}元</h3>
  5. <index1 :money="money" @xxx="handlerXXX"></index1>
  6. <h3>{{ son }}</h3>
  7. </div>
  8. </template>
  9. <script lang="ts" setup>
  10. import index1 from './view/index.vue'
  11. import { ref } from 'vue'
  12. let money = ref(1000000000000)
  13. let son = ref('')
  14. const handlerXXX = (value: string) => {
  15. son.value = value
  16. }
  17. </script>
  18. <style scoped>
  19. #app {
  20. width: 100vw;
  21. height: 100vh;
  22. color: #000;
  23. padding: 50px;
  24. box-sizing: border-box;
  25. }
  26. </style>

子组件

  1. <template>
  2. <div class="index1">
  3. <h1>子组件1</h1>
  4. <h3>儿子不知道父亲有{{ porps.money }}元</h3>
  5. <h3>
  6. 儿子知道了会争这{{ money }}元(template中可以直接省略porps---script中无法省略!)
  7. </h3>
  8. <p>
  9. vue2中 @click是自定义事件,可以通过.native修饰符变为原生DOM事件。
  10. 在vue3中@click是原生DOM事件
  11. </p>
  12. <el-button @click="handlerClick">自定义事件</el-button>
  13. </div>
  14. </template>
  15. <script setup lang="ts">
  16. import { ref } from 'vue'
  17. //------porps-------
  18. // porps:实现父子组件通信,props数据还是只读
  19. // 组合式api 使用 defineProps 接收父子组件传递过来的数据,可以是数组也可以是对象,
  20. //不需要引入 template中可直接使用
  21. const porps = defineProps(['money'])
  22. console.log(porps)
  23. //------$emit-------
  24. //defineEmits方法返回函数出发自定义事件,不需要引入 直接使用
  25. const $emit = defineEmits(['xxx'])
  26. const handlerClick = () => {
  27. console.log('触发自定义事件')
  28. $emit('xxx', '富二代上交9999元给富一代')
  29. }
  30. </script>
  31. <style lang="scss" scoped>
  32. .index1 {
  33. background-color: azure;
  34. padding: 12px;
  35. }
  36. </style>

 示例:

3.全局事件总线 $bus,使用mitt

Mitt是一个小巧的JavaScript发布-订阅库,用于在应用程序中实现事件监听和触发。

安装:npm install mitt -S

在src目录下新建bus文件夹,bus文件夹下新建index.ts

  1. // 引入mitt插件 index.ts
  2. import mitt from "mitt"
  3. const $bus = mitt();
  4. export default $bus

 接收组件:引入上面新建的bus,$bus.on  接收将来兄弟组件传递的数据

  1. <template>
  2. <div class="index1">
  3. <h1>子组件1</h1>
  4. <p>收到{{ car }}</p>
  5. </div>
  6. </template>
  7. <script setup lang="ts">
  8. import { ref ,onMounted} from 'vue'
  9. // 事件总线 引入$bus
  10. import $bus from '@/bus'
  11. let car = ref('')
  12. // 组件挂载完毕后,当前组件绑定一个事件,接收将来兄弟组件传递的数据
  13. onMounted(() => {
  14. $bus.on('car', (value: string) => {
  15. car.value = value
  16. })
  17. })
  18. </script>
  19. <style lang="scss" scoped>
  20. .index1 {
  21. background-color: azure;
  22. padding: 12px;
  23. }
  24. </style>

发送组件:$bus.emit 使用发送  

  1. <template>
  2. <div class="index2">
  3. <h1>子组件2</h1>
  4. <h3>富二代的亲弟钱包有999999元</h3>
  5. <el-button @click="handler">点击送富二代哥哥法拉利跑车一台</el-button>
  6. </div>
  7. </template>
  8. <script setup lang="ts">
  9. import $bus from '@/bus'
  10. const handler = () => {
  11. $bus.emit('car', '弟弟送哥哥的法拉利跑车一台')
  12. }
  13. </script>
  14. <style lang="scss" scoped>
  15. .index2 {
  16. background-color: antiquewhite;
  17. padding: 12px;
  18. margin: 12px 0;
  19. }
  20. </style>

示例:

4.v-model传值

在vue2中v-model绑定了一个value值,和input事件,并且只能绑定一个v-model。

而在vue3中给子组件传递一个porps,并且绑定了一个自定义事件。

此处有两种用法,方法一 

 porps + @update:money 代表自定义事件。代码如下:

 父组件代码:

  1. <template>
  2. <div id="app">
  3. <h1>父组件</h1>
  4. <!-- porps @update:money代表自定义事件,也可以换成其他名字 -->
  5. <!-- v-model
  6. 1.相当于子子组件传递props[modelValue]
  7. 2.相当于给子组件绑定了自定义事件update:modelValue
  8. -->
  9. <index3 :modelValue="money" @update:modelValue="handleMoney"></index3>
  10. <h3>父亲60大寿三妹送出价值{{ money3 }}元礼品</h3>
  11. </div>
  12. </template>
  13. <script lang="ts" setup>
  14. import index3 from './view/index3.vue'
  15. import { ref } from 'vue'
  16. // 接收子组件传递的数据
  17. let money3 = ref(666666)
  18. const handleMoney = (value: number) => {
  19. console.log('接收改变的值:' + value)
  20. money3.value = value
  21. }
  22. </script>
  23. <style scoped>
  24. #app {
  25. width: 100vw;
  26. height: 100vh;
  27. color: #000;
  28. padding: 50px;
  29. box-sizing: border-box;
  30. }
  31. </style>

子组件

  1. <template>
  2. <div class="index3">
  3. <h1>子组件3</h1>
  4. <h3>父亲送给三妹 {{ modelValue }}元</h3>
  5. <el-button @click="send">点击送出</el-button>
  6. </div>
  7. </template>
  8. <script setup lang="ts">
  9. // v-module :收集表单数据,数据双向绑定,组件之间的通信去实现父子数据同步业务
  10. defineProps(['modelValue'])
  11. let $emit = defineEmits(['update:modelValue'])
  12. const send = () => {
  13. $emit('update:modelValue', 9999)
  14. }
  15. </script>
  16. <style lang="scss" scoped>
  17. .index3 {
  18. background-color: beige;
  19. padding: 12px;
  20. }
  21. </style>

 方法二

1.相当于给子组件传递一个porps[modelValue]=666666 (一定叫modelValue)

2.相当于给子组件绑定了一个自定义事件,事件名一定是 update:modelValue,父组件不用自己写自定义事件

父组件代码

  1. <template>
  2. <div id="app">
  3. <h1>父组件</h1>
  4. <!-- v-model使用情况:1.相当于给子组件传递一个porps[modelValue]=100000 (一定叫modelValue)
  5. 2.相当于给子组件绑定了一个自定义事件,事件名一定是 update:modelValue
  6. 与vue2的v-model的区别在于,vue2的v-model绑定了一个value值,和input事件,
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/490205
    推荐阅读
    相关标签