乐趣区

关于vue.js:面试官Vue组件间通信方式都有哪些

一、组件间通信的概念

开始之前,咱们把 组件间通信 这个词进行拆分

  • 组件
  • 通信

都晓得组件是 vue 最弱小的性能之一,vue中每一个 .vue 咱们都能够视之为一个组件

通信指的是发送者通过某种媒体以某种格局来传递信息到收信者以达到某个目标。狭义上,任何信息的交通都是通信

组件间通信 即指组件 (.vue) 通过某种形式来传递信息以达到某个目标

举个栗子

咱们在应用 UI 框架中的 table 组件,可能会往 table 组件中传入某些数据,这个实质就造成了组件之间的通信

二、组件间通信解决了什么

在现代,人们通过驿站、飞鸽传书、战火报警、符号、语言、眼神、触碰等形式进行信息传递,到了明天,随着科技程度的飞速发展,通信根本齐全利用有线或无线电实现,相继呈现了有线电话、固定电话、无线电话、手机、互联网甚至视频电话等各种通信形式

从下面这段话,咱们能够看到通信的实质是信息同步,共享

回到 vue 中,每个组件之间的都有单独的作用域,组件间的数据是无奈共享的

但理论开发工作中咱们经常须要让组件之间共享数据,这也是组件通信的目标

要让它们相互之间能进行通信,这样能力形成一个有机的残缺零碎

二、组件间通信的分类

组件间通信的分类能够分成以下

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

关系图:

## 三、组件间通信的计划

整顿 vue 中 8 种惯例的通信计划

  1. 通过 props 传递
  2. 通过 $emit 触发自定义事件
  3. 应用 ref
  4. EventBus
  5. $parent 或 $root
  6. attrs 与 listeners
  7. Provide 与 Inject
  8. Vuex

### props 传递数据

  • 实用场景:父组件传递数据给子组件
  • 子组件设置 props 属性,定义接管父组件传递过去的参数
  • 父组件在应用子组件标签中通过字面量来传递值

Children.vue

props:{
    // 字符串模式
    name:String // 接管的类型参数
    // 对象模式
    age:{  
        type:Number, // 接管的类型为数值
        defaule:18,  // 默认值为 18
          require:true // age 属性必须传递
    }
}

Father.vue组件

<Children name:"jack" age=18 />

### $emit 触发自定义事件

  • 实用场景:子组件传递数据给父组件
  • 子组件通过 $emit 触发 自定义事件,$emit第二个参数为传递的数值
  • 父组件绑定监听器获取到子组件传递过去的参数

Chilfen.vue

this.$emit('add', good)

Father.vue

<Children @add="cartAdd($event)" />

### ref

  • 父组件在应用子组件的时候设置ref
  • 父组件通过设置子组件 ref 来获取数据

父组件

<Children ref="foo" />

this.$refs.foo  // 获取子组件实例,通过子组件实例咱们就能拿到对应的数据

### EventBus

  • 应用场景:兄弟组件传值
  • 创立一个地方工夫总线EventBus
  • 兄弟组件通过 $emit 触发自定义事件,$emit第二个参数为传递的数值
  • 另一个兄弟组件通过 $on 监听自定义事件

Bus.js

// 创立一个地方工夫总线类
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 的性能

Children1.vue

this.$bus.$emit('foo')

Children2.vue

this.$bus.$on('foo', this.handle)

### $parent 或 $root

  • 通过独特祖辈 $parent 或者 $root 搭建通信侨联

兄弟组件

this.$parent.on('add',this.add)

另一个兄弟组件

this.$parent.emit('add')

### $attrs 与 $listeners

  • 实用场景:先人传递数据给子孙
  • 设置批量向下传属性 $attrs$listeners
  • 蕴含了父级作用域中不作为 prop 被辨认 (且获取) 的个性绑定 (class 和 style 除外)。
  • 能够通过 v-bind="$attrs" 传⼊外部组件

    // child:并未在 props 中申明 foo
    <p>{{$attrs.foo}}</p>
    
    // parent
    <HelloWorld foo="foo"/>
// 给 Grandson 隔代传值,communication/index.vue
<Child2 msg="lalala" @some-event="onSomeEvent"></Child2>

// Child2 做开展
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>

// Grandson 使⽤
<div @click="$emit('some-event','msg from grandson')">
{{msg}}
</div>

### provide 与 inject

  • 在先人组件定义 provide 属性,返回传递的值
  • 在后辈组件通过 inject 接管组件传递过去的值

先人组件

provide(){
    return {foo:'foo'}
}

后辈组件

inject:['foo'] // 获取到先人组件传递过去的值

### vuex

  • 实用场景: 简单关系的组件数据传递
  • Vuex作用相当于一个用来存储共享变量的容器

  • state用来寄存共享变量的中央
  • getter,能够减少一个 getter 派生状态,(相当于 store 中的计算属性),用来取得共享变量的值
  • mutations用来寄存批改 state 的办法。
  • actions也是用来寄存批改 state 的办法,不过 action 是在 mutations 的根底上进行。罕用来做一些异步操作

### 小结

  • 父子关系的组件数据传递抉择 props$emit进行传递,也可抉择ref
  • 兄弟关系的组件数据传递可抉择 $bus,其次能够抉择$parent 进行传递
  • 先人与后辈组件数据传递可抉择 attrslisteners或者 ProvideInject
  • 简单关系的组件数据传递能够通过 vuex 寄存共享的变量

## 参考文献

  • https://juejin.cn/post/684490…
  • https://zh.wikipedia.org/wiki…
  • https://vue3js.cn/docs/zh

@JS 语音社群

退出移动版