★2019 前端进阶之路★Vue 组件间通信实战干货!

初体验

Vue.js 在现今使用有多广泛不用多说,而 Vue 的一大特点就是组件化。本期要讲的,便是 Vue 组件间通信方式的总结,这也几乎是近年 Vue 面试中的必考题。注:文中示例都基于 Vue 脚手架讲解,会用到一些 Element UI 示例。

【前端进阶之路】会作为一个新系列连载,后续会更多优质前端内容,感兴趣的同学不妨关注一下。

①组件

组件是可以复用的 Vue 实例。 — Vue 官方文档

在进入主题之前,还是决定先简单聊聊组件。在 Vue 中,根据注册方式的不同,可以分为:

    ▶局部组件 (局部注册)

    ▶全局组件 (全局注册)

顾名思义,全局注册的组件,可以用在 Vue 实例的任意模板中。但是带来的隐患是,在 webpack 模块化构建时,即便你没有在项目中使用这个组件,依然会打包到最终的项目代码中。而局部组件,则需要在使用到的实例中注册该组件。

根据应用场景的不同,又可以分为:

    1.页面组件:我们使用 Vue 时,每个路由代表的页面,都可以称之为组件。

    2.基础组件:就像上面栗子中的 Icon 组件,就是一个典型的基础组件。基本上不掺杂业务逻辑,在项目中可能被大量使用,易于移植。类似的基础组件还有 Button、Input 等,常见于各类 UI 组件库。

    3.业务组件:业务组件和项目具体的业务逻辑有大量耦合,一般抽离于当前项目。

以上就是组件的简单介绍,那我们到底为什么要推崇组件化?组件化有什么好处?复用?我个人认为组件化最大的好处,便是解耦,易于项目管理。所以在大型项目管理中,组件化是非常有必要的。当然,这并不是今天学习的重点,以后有机会再聊。

正因为在 Vue 中处处都是组件,而我们也偏向于组件化、模块化。那我们在一堆组件中,便需要解决一个问题 — 组件间通信。下面,我们就进入今天的主题,Vue 的组件间通信。

②组件间通信

组件间通信是我们在 Vue 项目中不可避免的问题,深刻了解了 Vue 组件间通信的几种方式,才能让我们在处理各种交互问题时游刃有余。

Props

Vue 中,最基本的通信方式就是 Props,它是父子组件通信中父组件传值给子组件的一种方式。它允许以数组形式接收,但是更推荐你开启类型检查的形式。更详细的类型检查前往 vue prop文档

我们都知道,Props 是单向数据流,这是 Vue 为了避免子组件意外改变父组件的状态,从而导致数据流向难以理解而做出的限制。所以 Vue 推荐需要改动的时候,通过改变父组件的值从而触发 Props 的响应。或者,我们可以在接收非引用类型的值时,使用子组件自身的 data 做一次接收。

为什么是非引用类型呢,因为在 JavaScript 中,引用类型的赋值,实际是内存地址的传递。所以上面栗子中的简单赋值,显然会指向同一个内存地址,所以如果是数组或是对象,你可能需要一次深拷贝。

上面这个操作有一些缺陷,不能序列化函数、undefined、循环引用等……

事实上,在 Props 是引用类型时,单独修改对象、数组的某个属性或下标,Vue 并不会抛出错误。当然,前提是你要非常清楚自己在做什么,并写好注释,防止你的小伙伴们疑惑。

有的同学可能知道,在组件上绑定的属性,如果没有在组件内部用 Props 声明,会默认绑定到组件的根元素上去。还是之前的栗子:

结果如下:

这是 Vue 默认处理的,而且,除了 class 和 style 采用合并策略,其它特性(如上栗 type)会替换掉原来根元素上的属性值。当然,我们也可以显示的在组件内部关闭掉这个特性:

利用 inheritAttrs,我们还可以方便的把组件绑定的其它特性,转移到我们指定的元素上。这就需要用到下一个我们要讲的 $attrs 了。

attrs、listeners

我们在使用组件库的时候经常会这么写:

实际渲染后:

可以看到我们指定的的 placeholder 是渲染在 input 上的,但是 input 并不是根元素。难道都用 Props 声明后,再赋值给 input?这种情况就可以用到 $attrs 了,改造一下我们之前那个栗子。


可以看到,type 已经转移到了子元素 input 标签上,但是 class 没有。这是因为inheritAttrs: false选项不会影响 style 和 class 的绑定。可以看出$attrs则是将没有被组件内部 Props 声明的传值(也叫非 Props 特性)收集起来的一个对象,再通过 v-bind 将其绑定在指定元素上。这也是 Element 等组件库采用的策略。

这里需要注意一点,通过 $attrs 指定给元素的属性,不会与该元素原有属性发生合并或替换,而是以原有属性为准。举个例子,假如我将上述 input 的 type 默认设置为 password。

则不会采用 $attrs 中的 type: 'text',将以 password 为准,所以如果需要默认值的属性,建议不要用这种方式。

$listeners同$attrs类似,可以看做是一个包含了组件上所有事件监听器(包括自定义事件、不包括.native修饰的事件)的对象。它也支持上述的写法,适用于将事件安放于组件内指定元素上。

给之前的栗子绑定一个聚焦事件,在子组件中通过$listeners绑定给 input,则会在 input 聚焦时触发。

那么除了用在这种给组件内指定元素绑定特性和事件的情况,还有哪些场景可以用到呢?官方说明:在创建更高层次的组件时非常有用。比如在祖孙组件中传递数据,在孙子组件中触发事件后要在祖辈中做相应更新。我们继续之前的栗子:在孙辈组件触发点击事件,然后在祖辈中修改相应的 data。

这样就能很方便的在多级组件的子级组件中,快速访问到父组件的数据和方法。正如在刚才的例子中,button 点击时,是直接调用的 communication.vue 中定义的方法。

总结:

1、子组件触达父组件的方式:Props、$parent、$attrs、$listeners、provide 和 inject、$dispatch

2、父组件触达子组件的方式:$emit和$on、$children、$ref、broadcast

3、全局通信:EventBus、Vuex

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容