Vue 组件间通讯方式

例子是在 jsrun.net 平台编写,不支持移动端平台,因此本文建议在 PC 端进行阅读。

Vue 是数据驱动的视图框架,那么组件间的数据通讯是必然的事情,那么组件间如何进行数据传递呢?html

首先组件间通讯有父子组件、兄弟组件、堂兄弟组件、叔侄组件等,分类太多可能很差理解,咱们暂且分为:vue

  • 父子组件通讯
  • 子父组件通讯
  • 非父子组件通讯react

    • 兄弟组件通讯
    • 非兄弟组件通讯(不是直属关系,如堂兄组件、叔侄组件等)

后续的组件间通讯方式的例子就会根据这些分类进行说明。git

Vue 自己提供哪几种通讯方式?

首先 Vue 灵感源于 angular,支持双向绑定,Vue 本质仍是单向数据流。跟 React 同样,组件间最基本的数据流是经过 prop 向子组件传递数据。github

props 数据流多层示例图

这里列举一下 Vue 自己支持的通讯方式:vuex

  • prop
  • $emit

    这个其实相似 React 的 props 回调。redux

  • provide / inject

    若是你熟悉 React,这与 React 的 context 特性很类似。api

那么有人说 $attrs$listener 呢?这些严格意义上不能概括为数据流的通讯方式,这些只是辅助属性,本人也不建议过多的使用这些 $ 属性,除了一些有必要的场景。框架

prop

prop 是 Vue 三大核心概念之一,prop 在组件中无处不在。prop 只能够从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。并且 prop 只读,不可被修改,全部修改都会失效并警告。ide

能够先阅读官网的 经过 Prop 向子组件传递数据 的教程。

父子组件通讯

这里也编写了一个简单的例子 http://jsrun.net/wXyKp/edit

子父组件通讯

不是说是单向数据流吗,怎么还可使用 prop 进行子父组件通讯?这样想是对的,prop 是没法向上传递数据,可是咱们可使用回调啊。数据流的确向上走了,可是这并不违反单向数据流的思想,这个并不会使得数据流混乱,仍是比较清晰。

这个 prop 回调方式,在 React 会常用。可是在 Vue 却不多使用,由于组件能够自定义事件,即后面的 $emit 组件间通讯方式(其实就是订阅发布模式)。

例子能够看这个 http://jsrun.net/aXyKp/edit

兄弟组件的通讯

若是你了解上面提到的父子组件通讯子父组件通讯,那么你就很容易理解兄弟组件通讯的方式。

能够看下这个例子 http://jsrun.net/QyyKp/edit

兄弟组件的通讯就是父子组件通讯子父组件通讯的结合,须要父组件做为中间组件进行数据传递。

那么这样岂不是很麻烦?的确是多了一步,因此咱们基本不会使用这种方式进行数据传递。

可是单向数据流思想是不存在交叉的数据流,即便 vuex 也没法避免这一步,可是 vuex 用法上你感受不到这一步。因此请不要随意引入第三方订阅发布的类库来解决这个问题,兄弟组件不能够直接通讯的问题,这会形成数据流混乱,这就彻底违反了单向数据流的思想。

能够看下这个强烈不建议的使用例子 http://jsrun.net/PyyKp/edit,这种使用方式彻底违背了单向数据流的思想,当程序复杂起来,数据流会特别混乱,项目很差维护。

$emit

官网教程能够看监听子组件事件

$on$emit 是 Vue 自带的订阅发布模式,能够自定义事件。在子父组件通讯中可使用这种模式代替 prop 回调模式,相对便捷一点。

每一个组件的 $on$emit 都是独立的,$emit 只会触发当前组件的 $on 事件。

对比例子能够看这个 http://jsrun.net/cXyKp/edit

子父组件通讯能够看上面提到的例子能够看这个 http://jsrun.net/aXyKp/edit

provide / inject

首先你须要看官网教程 https://cn.vuejs.org/v2/api/#...prviode / inject 在 vue@2.2.0 才新增的。这个也是做者参考 react context ,新加的用法,若是你熟悉 react,那么这个很好理解。

在组件嵌套比较深的状况下,咱们再使用 prop 层层传递数据将是个噩梦。 孙辈组件想直接获取到祖辈的数据,而不用通过父辈组件,该怎么处理呢?provide / inject 能够解决这个问题。

可看这个使用例子 http://jsrun.net/nXyKp/edit

从上面的例子运行可知,provide 执行与 beforeCreatecreated 之间,也能够访问 datainject 的数据。

其余的通讯方式

除了 vue 自己支持的通讯方式,还有其余的吗?固然有 vuex 就是 vue 官方的数据流管理类库。

上面提到的 vue 自己支持的通讯方式,涉及到的都是父子或者子父组件的通讯,那么非父子组件通讯呢?经过 vuex 咱们就能够很简单的进行非父子组件的通讯了,使用了 vue 支持各类方式的通讯(包括父子组件、子父组件的通讯)。

结合单向数据流的思想,咱们难道不能够统一一个地方集中管理数据(咱们简称 store),而后每一个组件能够直接和 store 通讯吗?答案固然能够,这就是咱们 vuex 所作的事情,这个跟 react 的 redux、mobx 等类库的思想是一致的。

props 的通讯方式是这样的,component -> component

而 vuex 的通讯方式是这样的,component(传递数据) -> store -> (数据变化更新组件)component,能够简单理解为 component -> store -> component。咱们在中间搭建了数据管理层,那么这样咱们就能够更好的管理数据了,并且数据流符合单向数据流的思想,数据都是从 store 流向 componentcomponent 能够是任何嵌套层次的组件。

理论上咱们也能够在 vue 上使用 redux,可是没人会这样作,不合适,vuex 才是量身定制的。

参考文章


学习和总结文章同步发布于 https://github.com/xianshanna...,有兴趣能够关注一下,一块儿学习和进步。