当前位置: 首页 > news >正文

Vue组件间通信的方式

组件间通信的分类:

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件间之间的通信

组件间通信的方案:

  • 通过 props 传递
  • 通过 $emit 触发自定义事件
  • 使用 ref
  • EventBus
  • 通过 $parent 或 $root
  • attrs 与listeners
  • Provide 与 Inject
  • Vuex/Pinia

EventBus

  • 使用场景:兄弟组件传值
  • 创建一个中央事件总线EventBus
  • 兄弟组件通过 e m i t 触发自定义事件, emit触发自定义事件, emit触发自定义事件,emit第二个参数为传递的数值
  • 另一个兄弟组件通过$on监听自定义事件
// 创建一个中央时间总线类  
class Bus {  
  constructor() {  
    this.callbacks = {};   // 存放事件的名字  
  }  
  $on(name, fn) {  
    this.callbacks[name] = this.callbacks[name] || [];  
    this.callbacks[name].push(fn);  
  }  
  $emit(name, args) {  
    if (this.callbacks[name]) {  
      this.callbacks[name].forEach((cb) => cb(args));  
    }  
  }  
}  
  
// main.js  
Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上  
// 另一种方式  
Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能  
// 组件1
this.$bus.$emit('foo')  
// 组件2
this.$bus.$on('foo', this.handle)  

$parent 或 $root

通过共同祖辈$parent或者 $root搭建通信桥连
兄弟组件1:
this. $parent.on(‘add’,this.add)
兄弟组件2:
this. $parent.emit(‘add’)

$attrs 与 $ listeners

  • 适用场景:祖先传递数据给子孙
  • 设置批量向下传属性$attrs和 $listeners
  • 包含了父级作用域中不作为 prop 被识别,(且获取) 的特性绑定 ( class 和 style 除外)。
  • 可以通过 v-bind=“$attrs” 传⼊内部组件
实现原理

属性传递:爷爷组件将一些属性传递给父组件,父组件通过 $attrs 将这些属性传递给孙子组件。
事件监听器传递:爷爷组件绑定了一些事件监听器到父组件,父组件通过 $listeners 将这些监听器传递给孙子组件。

vue2.x 使用
// grandpa.vue

<template>
  <div class="grandpa">
    <h2>爷组件</h2>
    <div>{{ msg }}</div>
    <parent :message="message" :message2="message2" @sendGradpaMessage="getMessage"/>
  </div>
</template>

<script>
import parent from './parent.vue';

export default {
  name: 'grandpa',
  data() {
    return {
      message: 'This is some shared data1',
      message2: 'This is some shared data2',
      msg:""
    }
  },
  components: {
    parent
  },
  methods:{
    getMessage(msg){
      console.log('msg::: ', msg);
      this.msg = msg
    },
  }
}
</script>

// parent.vue

<template>
  <div class="parent">
    <h2>父组件</h2>
    <div>{{ message }}</div>
    <son v-bind="$attrs" v-on="$listeners"/>
  </div>
</template>

<script>
import son from './son.vue';

export default {
  name: 'parent',
  data() {
    return {

    }
  },
  components: { son },
  computed: {
    message() {
      // 从 $attrs 中删除已定义的 prop
      console.log('this.$attrs::: ', this.$attrs);
      const { message} = this.$attrs;
      return message;
    }
  },
}
</script>

// son.vue

<template>
  <div class="son">
    <h2>孙组件</h2>
    <div>{{ $attrs.message }}</div> 
    <div>{{ message }}</div> 

    <el-button type="primary" @click="sendMessage">发送消息</el-button>
  </div>
</template>

<script>
export default {
  name: 'son',
  data() {
    return {

    }
  },
  computed: {
    message() {
      // 从 $attrs 中删除已定义的 prop
      console.log('this.$attrs::: ', this.$attrs);
      const { message2} = this.$attrs;
      return message2;
    }
  },
  methods: {
    sendMessage(){
      const msg = 'Hello from son component!';
      this.$emit('sendGradpaMessage', msg)
    }
  }
}
</script>

  • grandpa.vue 组件提供了 message, message2 两个参数。
  • parent.vue 组件通过 $attrs 接收了 message 参数,并在模板中使用 message。
  • son.vue 组件通过 $attrs 接收了 message2 参数,并在模板中使用 message,同时通过点击按钮使用 $emit方法将参数 msg 传给了 parent.vue 组件,parent.vue 通过 $listeners 将事件传递给grandpa.vue。
vue3.x 使用

在 Vue 3 中,$attrs 和 $listeners 的使用有一些变化,特别是在 $listeners 的处理上。Vue 3 已经不再单独提供 $listeners,而是将事件监听器和其他属性一起放在 $attrs 中。这意味着在 Vue 3 中,你需要通过 $attrs 来传递所有的属性和事件监听器。

// grandpa.vue

<template>
  <div class="grandpa">
    <h2>爷组件</h2>
    <div>{{ receive }}</div>
    <parent :message="message" :message2="message2" @sendGrandpaMessage="getMessage" />
  </div>
</template>

<script setup lang="ts" name="grandpa">
import { ref } from 'vue';

import parent from './parent.vue';

// 定义一个可变的值
const message = ref('Hello from grandpa');
const message2 = ref('Hello from Parent');

// 定义一个接收消息
const receive = ref('111');

// 接收子组件传的参数
const getMessage = (msg: string) => {
  console.log('msg::', msg);
  receive.value = msg
};
</script>

// parent.vue

<template>
  <div class="parent">
    <h2>父组件</h2>
    <div>{{ message2 }}</div>
    <div>{{ $attrs }}</div>

    <son v-bind:="$attrs" />
  </div>
</template>

<script setup lang="ts" name="parent">
import son from './son.vue';

defineProps(['message2']);
</script>

// son.vue

<template>
  <div class="son">
    <h2>孙组件</h2>
    <div>{{ message }}</div>
    <el-button type="primary" @click="sendMessage()">发送消息</el-button>
  </div>
</template>

<script setup lang="ts" name="son">
import { defineProps, defineEmits } from 'vue';

defineProps(['message',]);

const emits = defineEmits(['sendGrandpaMessage']);

// 处理事件
function sendMessage() {
  const msg = 'Hello from child';
  emits('sendGrandpaMessage', msg);
}
</script>

  • grandpa.vue 组件提供了 message, message2 两个参数和 sendGrandpaMessage 方法
  • parent.vue 组件通过 $attrs 接收了 message2 参数,并在模板中使用 message2。
  • son.vue 组件通过 $attrs 接收了 message 参数,并在模板中使用 message,同时通过点击按钮使用 emit 将参数 msg 传给了parent.vue 组件,parent.vue 通过 $attrs 将事件传递给 grandpa.vue。

provide 与 inject

在祖先组件定义provide属性,返回传递的值
在后代组件通过inject接收组件传递过来的值

相关文章:

  • 升级Office软件后,Windows 系统右键里没有新建Word、Excel、PowerPoint文件的解决办法
  • OA办公系统自动渗透测试过程
  • 树和二叉树
  • 线性回归 (Linear Regression)案例分析1
  • 数据处理(二)| 打磨数据,提升模型:全面解读图像数据质量评估
  • 在自己的数据上复现一下LlamaGen
  • 开发HarmonyOS NEXT版五子棋游戏实战
  • 【Linux】vim 设置
  • 深入理解 Linux 中的 last 和 lastb 命令
  • OpenGL 04--GLSL、数据类型、Uniform、着色器类
  • Unity XR-XR Interaction Toolkit开发使用方法(十一)组件介绍(XR Interactable)
  • 在单位,领导不说,但自己得懂的7个道理
  • LSM-Tree (日志结构合并树)
  • Linux 运维工具-下载多个链接wget,aria2c
  • 06.【C++】模板初阶(template<typename T>,充分复用函数,函数模板和类模板的使用)
  • C#实现本地Deepseek模型及其他模型的对话
  • 在服务器Ubuntu22.04系统下,ComfyUI的部署
  • JavaScript系列(89)--前端模块化工程详解
  • centos和ubuntu安装mysql教程
  • 基于 Python 的网络监控系统开发全解
  • 做得好的网站建设公司/google 谷歌
  • 海报素材网站推荐/抖音代运营收费详细价格
  • 专业网站定制 北京/小企业广告投放平台
  • 指纹锁在什么网站做宣传好/网推接单平台有哪些
  • 动态网站开发作业/主要推广手段免费
  • 杭州网站改版公司电话/人工智能培训师