博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue组件通信的几种方式
阅读量:7260 次
发布时间:2019-06-29

本文共 3443 字,大约阅读时间需要 11 分钟。

父组件通过 Prop 向子组件传递数据

这个数据流是单向的。数据流向是从父组件传到子组件。也就是说,父级 prop 的更新会向下流动到子组件中,但是反过来则不行。

现在我们需要写一个博文组件,展示博文的标题和内容。标题和内容这些数据是从父组件获得的。
第一步,定义一个组件,这里用注册全局组件的方式,子组件用prop接收来自父组件的数据:

Vue.component('blog-post', {  props: ['post'],  template: `    

{
{ post.title }}

`});

第二步,初始化一个Vue实例并挂载到对应的HTML结构:

// html
// jsnew Vue({ el: "#app", data: { postArr: [ { title: 'My name is Judy', content: 'something here ' }, { title: 'My job is coding', content: 'something here ' }, { title: 'I like coding', content: 'something here ' } ] }});

demo:

子组件通过事件向父级组件发送消息

在我们开发 <blog-post> 组件时,它的一些功能可能要求我们和父级组件进行沟通。例如我们可能会引入一个可访问性的功能来放大博文的字号,同时让其他部分的博文保持默认的字号。

还是刚才那个demo,在其父组件中,我们可以通过给每一条博文的数据添加一个 postFontSize 数据属性来控制每篇博文字体的大小。

// jsnew Vue({  el: "#app",  data: {    postArr: [      {        postFontSize: 1,          title: 'My name is Judy',        content: 'something here '      },      {        postFontSize: 1,          title: 'My job is coding',        content: 'something here '      },      {        postFontSize: 1,        title: 'I like coding',        content: 'something here '      }    ]  }});

现在我们需要给子组件添加一个按钮。当点击这个按钮时,我们需要告诉父级组件放大所有博文的文本。刚好 Vue 实例提供了一个自定义事件的系统来解决这个问题。我们可以调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件。改写一下子组件:

Vue.component('blog-post', {  props: ['post'],  template: `    

{
{ post.title }}

`});

然后我们可以用 v-on 在博文组件上监听这个事件,就像监听一个原生 DOM 事件一样:

demo:

以上为常用的父组件向子组件传递数据、子组件通过事件向父级组件发送消息的两种方式。

$parent访问父级组件实例

$parent 属性可以用来从一个子组件访问父组件的实例。它提供了一种机会,可以在后期随时触达父级组件,以替代将数据以 prop 的方式传入子组件的方式,实际上这不是一种数据传递,而是子组件主动发起的数据查找。

但是Vue并不推荐这么做。在绝大多数情况下,触达父级组件会使得我们的应用更难调试和理解,尤其是我们变更了父级组件的数据的时候。当我们稍后回看那个组件的时候,很难找出那个变更是从哪里发起的。
在一些可能适当的时候,我们需要特别地共享一些组件库,就可以考虑用$parent。Vue官网称这些情况为【边界情况】。
假设有一个Google地图组件:

这个 <google-map> 组件可以定义一个 map 属性,所有的子组件都需要访问它。在这种情况下 <google-map-markers> 可以通过类似 this.$parent.getMap 的方式访问那个地图,以便为其添加一组标记。

ref 特性访问子组件实例或子元素

尽管存在 prop 和事件,有的时候仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,我们可以通过 ref 特性为这个子组件赋予一个 ID 引用。

例如:

现在在已经定义了这个 ref 的组件里就可以使用:

this.$refs.usernameInput

来访问这个 <base-input> 实例,以便不时之需。

另外,vm.$children也可以访问当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。

当我们需要访问子组件或者子元素,推荐使用 ref 而不是 $children

因为 ref 能帮我们访问到的是任意子组件实例或者子元素,$children 只能访问到直接子组件

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

什么意思呢?在实际开发中,我们会遇到有一处或者多处需要被多个实例间共享的状态,Vuex就是为我们提供了这样一个模式。所以我的理解是Vuex不仅仅是适用于父子组件的通信了,它适用于所有组件共享某些必要的数据状态。
关于Vuex的使用我们这里不详细展开讨论了,贴一个。

一些补充

前面我们提到google地图组件,类似这样的:

在这个组件里,所有 <google-map> 的后代都需要访问一个 getMap 方法,以便知道要跟那个地图进行交互。不幸的是,使用 $parent 属性无法很好的扩展到更深层级的嵌套组件上,也就是说,只有<google-map-region>能通过 $parent 访问到它的直接父组件<google-map>的 getMap 方法。这种情况可以用依赖注入 provideinject 解决。

provide 选项允许我们指定我们想要提供给后代组件的数据/方法。在这个例子中,就是 <google-map> 内部的 getMap 方法:

provide: function () {  return {    getMap: this.getMap  }}

然后在任何后代组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性:

inject: ['getMap']

相比 $parent 来说,这个用法可以让我们在任意后代组件中访问 getMap,而不需要暴露整个 <google-map> 实例。这允许我们更好的持续研发该组件,而不需要担心我们可能会改变/移除一些子组件依赖的东西。同时这些组件之间的接口是始终明确定义的,就和 props 一样。

实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:

  • 祖先组件不需要知道哪些后代组件使用它提供的属性
  • 后代组件不需要知道被注入的属性来自哪里

我看了很多篇总结Vue父子组件通信方式的博客都没有提到依赖注入,不过我觉得依赖注入也实现了通信——由父组件通过 provide 把数据暴露出去,子组件通过 inject 接收数据。

以上就是我阅读官方文档总结出来的Vue组件通信的几种方式,大部分内容和demo都来源于官网文档,了解更多可以阅读文档:。

文章全部内容仅代表个人观点,欢迎批评或者与我讨论。感谢你的阅读。

转载地址:http://yxkdm.baihongyu.com/

你可能感兴趣的文章
AgileEAS.NET平台开发实例-药店系统-报表开发(上)
查看>>
3 weekend110的hadoop中的RPC框架实现机制 + hadoop中的RPC应用实例demo
查看>>
《高效程序员的修炼》 读书笔记
查看>>
Nature:中国正在上演AI人才争夺战,中国公司在与Google竞争
查看>>
VS代码提示不出现或者提示变成英文或者各种奇葩问题的解决
查看>>
WGS 1984 Web Mercator 对于在线地图服务的意义
查看>>
Word2vec 讨论
查看>>
HBase编程 API入门系列之put(客户端而言)(1)
查看>>
percona-toolkit之pt-kill:杀掉mysql查询或连接
查看>>
JavaScriptSerializer 对json数据转换
查看>>
重裝系統,磁盤消失解決方法
查看>>
11.13. Highslide
查看>>
Visual Studio 11 Beta 带来新的Metro 应用开发体验
查看>>
最佳实践: 勿在 Servlet 中实现 SingleThreadModel
查看>>
IIS发生意外错误0x8ffe2740
查看>>
架构设计中服务层的简单理解
查看>>
一般的相关分析代码
查看>>
单片机系列学习
查看>>
[LeetCode] Combinations
查看>>
java中的几种对象(PO,VO,DAO,BO,POJO)
查看>>