VUE面试,组件通讯

VUE面试,组件通讯_第1张图片

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

30. 举一个$attrs 和 $listeners 的应用场景

比如,有 A、B、C 三个组件,调用关系如下: A -> B -> C

B 调用 C 时,在 C 上写$attrs$listeners,就可以把 C 的属性和事件绑定在 B身上,A 调用 B 时,就可以拿到 C 上的属性和事件。

这种写法在对一些组件进行二次封装时非常有用,比如,对 element-ui 的级联选择器组件 el-cascader 进行二次封装,只改了很小的一个功能,其他功能保持原样。

就可以定义一个 custom-cascader 组件

custom-cascader 内部
...

...
调用 custom-cascader 的地方

VUE面试,组件通讯_第2张图片

VUE面试,组件通讯_第3张图片

这些 el-cascader 的属性和事件都可以直接使用,不用再通过 props 传递一层了,非常方便。

31. 用过 provide 和 inject 吗?

provide 和 inject 一般用于层级很深的组件之间通信。

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。 -- vue文档

日常的业务组件一般不会用,因为容易造成混淆,而且一般的项目都用了 Vuex

provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。 -- vue文档

正如文档所说, provide 和 inject 用来开发组件库很有用,因为一般开发组件库不会引类似于 Vuex 这样的三方依赖,就只有用 Vue 本身提供的 provide 和 inject 了。

比如, element-ui 的源码中就大量地使用到了 provide 和 inject。

VUE面试,组件通讯_第4张图片

而且他的用法是直接把这个组件实例 provide 过去,像这样

VUE面试,组件通讯_第5张图片

需要用到的地方,直接调这个实例上的属性和方法

VUE面试,组件通讯_第6张图片

provide 和 inject 基本使用

当然,vue 文档虽然不推荐我们在业务开发中用,但有时候用一用还是无伤大雅的,provide 和 inject 基本使用如下:

// A.vue
export default {
  provide: {
    name: 'lin'
  }
}

// B.vue
export default {
  inject: ['name'],
  mounted () {
    console.log(this.name);  // lin
  }
}

可以看到,在 A.vue 里,我们设置了一个 provide: name,值为 lin,它的作用就是将 name 这个变量提供给它的所有子组件。

而在 B.vue 中,通过 inject 注入了从 A 组件中提供的 name 变量,那么在组件 B 中,就可以直接通过 this.name 访问这个变量了,它的值也是 lin。

32. provide 和 inject 是响应式的吗?

provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。 -- vue 文档

写个 demo 试一试:

// 父组件内:


data() {
  return {
    name: 'lin',
    person: {
      name: 'Allen'
    }
   }
},
provide() {
  return {
    name: this.name,
    person: this.person
  }
},
methods: {
  changeName() {
    this.name = 'lin12345'
    this.person.name = 'Adel'
  }
}
// 子组件内:

{{ name }}

{{ person }}

inject: ['name', 'person']

VUE面试,组件通讯_第7张图片

果然如此,一般的变量不可响应,传入对象,对象的属性可以响应。

33.Vue 组件之间的通信方式有哪些?

常用的:

  • 父子组件交互,props 和 $emit,vue单向数据流。

  • 使用$attrs$listeners,集成子组件的属性和事件,在对一些组件进行二次封装时非常有用,可以不用写具体的属性或事件名,直接获取。

  • 使用Vuex进行状态管理

不常用的:

  • 使用$refs获取组件实例,进而获取数据

  • 组件中可以使用 $parent 和 $children 获取到父组件实例和子组件实例,进而获取数据

  • 使用eventBus进行跨组件触发事件,进而传递数据,一般用得比较少

  • 使用provideinject,一般用于基础组件开发,或用于跨很多层的组件传值。

  • 通过 mixins 传公共逻辑。

其实,像provide/inject还有 mixins这种通信方式,写组件库没啥,但最好不要用在业务组件里。

因为项目复杂了之后,很容易造成迷惑,不知道数据是从哪里传递过来的,全局搜调用的属性名或者函数名,结果出来很多个,太令人难受了。

如果是通过文件夹的形式管理业务组件,每个文件夹有自己内部的mixins,这种方式还是可以接受的。

VUE面试,组件通讯_第8张图片

但其实也很难受,日常代码开发由上下横跳变成左右横跳,不过这样可以让我们的单个文件代码少一点,还是要优雅一点。

像 $refs$parent$children,我一般也用得少,除非迫不得已一定要用,因为这些组件通信方式用了之后,数据的流向不是一目了然的,在这个文件里搜属性或者方法,搜不到来源,要把这个文件的代码仔细读一下才能清楚数据流向,开发效率就降低了。

 

 

 

 

 

 

 

 

你可能感兴趣的:(前端,vue.js,面试,前端框架)