Vue面试之组件通信的方式总结(下篇)

Vue面试之组件通信的方式总结

最近在整理一些前端面试中经常被问到的问题,分为vue相关、react相关、js相关、react相关等等专题,可持续关注后续内容,会不断进行整理~

在Vue框架中,提供了多种组件通信方式:props父子组件传参、插槽传参、Event Bus方式、vuex方式传参等,之前已对前两种方式进行了总结,本文继续总结其余方法~

$ref

在Vue中很少会直接操作DOM,但是一般情况下会用ref和 refs取某DOM结构,具体来说:利用ref给元素或子组件注册信息,则该信息就会被注册到父组件的 refs对象上。
$refs是一个对象,包含已经注册过ref的所有子组件的内容

ref有三种用法:

  1. ref加在普通元素上,则通过this.$refs.xxx获取到的是dom元素;
html 复制代码
<p id="p1" ref="p1">这是第一段</p>
javascript 复制代码
console.log(this.$refs.p1) // 就可以拿到p1对应的dom元素
  1. ref加在子组件上,则通过this.$refs.xxx获取到的是组件,可拿到子组件的所有属性和方法,实现子组件向父组件通信;同时如果在使用子组件方法时传入参数,则可以实现父组件向子组件通信;

上图展示了利用this.refs.xxx可以获取到子组件身上的所有属性和方法,从而实现子组件向父组件通信;

这里需要注意的一点是,$refs只有在子组件被渲染后才能拿到,使用时一定要确保子组件已经被渲染,否则拿到的只能是undefined

父组件利用子组件的submit方法,可在使用时传递参数,这样调用时,子组件就可以拿到传递过来的参数值,实现父组件向子组件的通信;

html 复制代码
<!-- 父组件中 -->
<Son ref="son"></Son>
<button @click="finish">提交</button>
javascript 复制代码
// 父组件中 
finish() {
	this.$refs.son.submit('12')
	// 调用子组件中的submit方法,并将12作为参数传递
}
javascript 复制代码
// 子组件中 
submit(params) {
	console.log('拿到了父组件传递过来的参数', params)
	// 可以拿到父组件传递过来的参数12
}
  1. 如果使用 v-for 渲染多个相同类型的子组件,$refs 将成为一个数组。

provide&inject

provideinject 也可以用来进行跨层级组件通信,父组件通过provide提供数据或方法,而子孙组件通过inject拿到数据或方法;

provide

它有两种写法:

  1. 对象写法
    如果传递的数据是个'死数据'(静态数据),则可以直接利用对象形式将其传递;
javascript 复制代码
// Parent.vue
export default {
// provide对象写法,直接将数据进行传递
  provide: {
  	age: 13
  },
};
  1. 函数写法
javascript 复制代码
// Parent.vue
export default {
  data() {
    return {
      list: [...], // 一些数据
    };
  },
  provide() {
  // provide函数写法,可以将动态数据传递
    return {
      list: this.list, // 提供属性
      submit: this.submit // 提供方法
    };
  },
  methods: {
    submit() {
      // 一些逻辑
    }
  }
};

inject

inject的写法也有两个:

  1. 数组写法
    如果不用给传递过来的数据重命名,可采用此方法(上例中的传递age)
javascript 复制代码
// Child.vue
export default {
  inject: ['age'], // 数组形式
  mounted() {
    console.log(this.age); // 可以访问父组件提供的数据,12
  },
};
  1. 对象形式
    如果需要对传递过来的数据重命名,可采用对象形式(上例中传递submit与list)
javascript 复制代码
// Child.vue
export default {
  inject: {
    parentList: 'list',
    parentSubmit: 'submit'
  },
  mounted() {
    console.log(this.parentList); // 可以访问父组件提供的数据
    this.parentSubmit(); // 可以调用父组件提供的方法
  },
};

需要注意的是,provide 提供的数据不是响应式的,这意味着如果提供的数据发生变化,子组件不会自动重新渲染。如果需要响应式数据,可以使用 Vue 的实例或 Vuex 等状态管理工具。

EventBus事件总线

事件总线是一种简单而有效的组件通信方式,它通过一个中央的事件总线来传递消息,允许不同组件之间进行解耦合的通信。它属于** 订阅/发布模式实现的一种方式,通常可以通过创建一个全局的Vue实例**作为事件总线。分为如下几个步骤:

  1. 创建事件总线实例
javascript 复制代码
// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
  1. 在父组件中发送事件,使用$emit
javascript 复制代码
// 父组件
import { EventBus } from '@/utils/eventBus.js'
showDetails (val) {
      EventBus.$emit('message-event', '12')
      // 发送message-event事件,传递12这个数据
    },
  1. 在子组件中接收事件,使用$on
javascript 复制代码
// 子组件
import { EventBus } from '@/utils/eventBus.js'
mounted() {
  EventBus.$on('message-event', this.doSomething)
   // 当message-event发生改变时,就会触发doSomething方法
},
methods() {
 doSomething(params) {
    console.log('被事件触发了此方法~')
    console.log('并能接收到了数据', params)
  }
}
  1. 为防止内存泄露,一般在组件卸载时需要解绑事件总线,使用$off
javascript 复制代码
// 子组件
 beforeDestroy() {
    EventBus.$off('message-event', this.doSomething);
    // 解绑message-event事件
  },

在解绑事件时,off 方法的第二个参数是一个可选的回调函数。如果在 on 时使用了具名的回调函数,可以在 $off 时只传递回调函数而省略事件名称,这样就能够更精确地解绑特定的回调函数,如:

javascript 复制代码
beforeDestroy() {
  EventBus.$off(this.doSomething);
},
  1. 在大型应用中,为了防止命名冲突,可以考虑使用命名空间来管理事件总线。可以在 EventBus.js 中为每个模块或组件创建一个子实例,以确保事件名称的唯一性。
javascript 复制代码
// EventBus.js
import Vue from 'vue';
export const ParentEventBus = new Vue();
export const ChildEventBus = new Vue();
javascript 复制代码
// 父组件
import { ParentEventBus } from '@/utils/eventBus.js'

注意:

尽量避免滥用事件总线,特别是在大型应用中。对于父子组件通信或兄弟组件通信,更推荐使用 props 和 $emit;

在多人协作或大型项目中,可能会使用更为复杂的状态管理工具(例如 Vuex)来代替事件总线;

vuex

该方式在以往文章中已经进行了详细的讲述,请移步Vue2教程详解七(Vuex3)

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端