Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day96:请能尽可能多的说出 Vue 组件间通信方式?在组件的通信中EventBus非常经典,你能手写实现下EventBus么? #908

Open
Genzhen opened this issue Jul 13, 2020 · 1 comment
Labels
Vue teach_tag

Comments

@Genzhen
Copy link
Collaborator

Genzhen commented Jul 13, 2020

No description provided.

@Genzhen
Copy link
Collaborator Author

Genzhen commented Jul 13, 2020

每日一题会在下午四点在交流群集中讨论,五点 Github、交流群同步更新答案

一、Vue组件通信方式

Vue 组件间通信是面试常考的知识点之一,这题有点类似于开放题,你回答出越多方法当然越加分,表明你对 Vue 掌握的越熟练

Vue 组件间通信主要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信

下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

1.props / $emit

适用于父子组件通信

这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。

2.ref$parent / $children

适用于父子组件通信

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

3.EventBus ($emit / $on)

适用于父子、隔代、兄弟组件通信

这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

4.$attrs/$listeners

适用于隔代组件通信

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件

5.provide / inject

适用于隔代组件通信

祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。

provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

6.Vuex

适用于父子、隔代、兄弟组件通信

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

二、手写实现简版EventBus

// 组件通信,一个触发与监听的过程
class EventEmitter {
    constructor () {
      // 存储事件
      this.events = this.events || new Map()
    }
    // 监听事件
    addListener (type, fn) {
      if (!this.events.get(type)) {
        this.events.set(type, fn)
      }
    }
    // 触发事件
    emit (type) {
      let handle = this.events.get(type)
      handle.apply(this, [...arguments].slice(1))
    }
  }
  // 测试
  let emitter = new EventEmitter()
  // 监听事件
  emitter.addListener('ages', age => {
    console.log(age)
  })
  // 触发事件
  emitter.emit('ages', 18)  // 18

@Genzhen Genzhen added the Vue teach_tag label Jul 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Vue teach_tag
Projects
None yet
Development

No branches or pull requests

1 participant