Angular2 父子组件数据通信实例


Posted in Javascript onJune 22, 2017

如今的前端开发,都朝组件式开发模式靠拢,如果使用目前最流行的前端框架Angular和React开发应用,不可避免地需要开发组件,也就意味着我们需要考虑组件间的数据传递等问题,不过Angular 2已经为我们提供了很好的解决方案。

父组件和子组件

接触过面向对象编程的开发者肯定不会对父子关系陌生,在Angular 2中子组件存在于父组件“体内”,并且父子组件可以通过一些渠道进行通讯。

父组件向子组件传入数据 ? @Input

当我们着手开始开发一个组件时,第一件想到的应该就是为其传入数据,毕竟我们期望组件为我们处理某些工作通常就需要给其提供“养料”,毕竟不能又让马儿跑,又不给马儿吃草。Angular 2中子组件使用装饰器@Input接收父组件传入的数据:

// child-component.ts
import { OnInit, Component, Input } from '@angular/core';

@Component({
  selector: 'child-component',
  ...
})
export class ChildComponent implements OnInit {
  @Input
  count: number = 0;

  ngOnInit() {
    console.log(this.count);  // 父组件内传入的值或者我们自己设置的初始值0
  }

  increaseNumber() {
    this.count ++;
  }

  descreaseNumber() {
    this.count --;
  }
}

可以看到,我们使用装饰器@Input修饰了count属性,这就意味着child-component被使用时期望收到一个名为count的属性,当然不属于自己掌控的范围内要小心行事,别人使用我们的组件时什么情况都可能出现,所以我们为count设置了一个初始值,当父组件没有给我们的count属性传值时,我们就取此初始值。

// father-component.ts
import { Component } from '@angular/core';
import { ChildComponent } from '../child-component/child-component';

@Component({
  template: `
    <child-component [count]='initialCount'></child-component>
  `,
  ...
})
export class FatherComponent {
  initialCount: number = 5;
}

父组件使用child-component时,为count属性赋予初始值initialCount,即5,也就是说此时ChildComponent的ngOnInit方法中会打印出5。注意[count]语法标识了数据流向:父组件流入子组件,即单向数据绑定。此时如果传入的数据是基本数据类型,子组件中对数组做任何操作都不会影响到父组件,但如果传入的不是基本数据类型,而是引用数据类型,则要格外注意子组件中对数据的操作可能会对父组件产生影响。

子组件通知父组件数据已处理完成 ? @Output、EventEmitter

父组件传入数据给子组件之后并不是万事大吉了,就像父母养育孩子,供其读书,但孩子需要把学习进度、考试成绩等呈现给父母看(不管是否自愿…),父组件也需要子组件在合适的时机通知自己数据已经处理好,可以检阅了。而此时就需要使用@Output和EventEmitter了。

// father-component.ts
import { Component } from '@angular/core';
import { ChildComponent } from '../child-component/child-component';

@Component({
  template: `
    <child-component [count]='initialCount' (change)="countChange($event)"></child-component>
  `,
  ...
})
export class FatherComponent {
  initialCount: number = 5;

  countChange($event) {

  }
}

看看我们在父组件中加入了什么东东:

1.(change),看到这样的语法第一时间就知道这是事件绑定,也就是说我们在父组件中监听子组件的某些变化,并能够在其变化时作出相关操作;

2.增加了countChange方法作为change事件的处理函数。

但是稍等,当我们为input标签指定type、placeholder等属性时,我们知道它们都已经被“实现了”,所谓“实现”,即这些属性在input标签上是有意义的。但是目前这里我们为child-component指定了名为change的事件是没意义的,因为其并未“实现”change事件,于是下一步我们就需要使用@Output和EventEmitter将其变得有意义:

// child-component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'child-component',
  ...
})
export class ChildComponent {
  @Input
  count: number = 0;

  @Output
  change = new EventEmitter();

  increaseNumber() {
    this.count ++;
    this.change.emit(this.count);
  }

  descreaseNumber() {
    this.count --;
    this.change.emit(this.count);
  }
}

让我们再来看看在子组件中增加了什么东东:

1.使用装饰器@Output修饰了change属性,并为其赋了初值为EventEmitter的实例;

2.在increaseNumber和descreaseNumber方法修改了count属性后,调用了change属性的emit方法通知父组件。

此时,我们在ChildComponent中实现了change,于是父组件中为child-component绑定change事件也就有意义了:当子组件通知父组件时,父组件可以获取到通知中携带的数据并进行下一步操作:

// father-component.ts
...
countChange($event) {
  this.initialCount = $event;
}
...

总结

不知道你有没有发现,其实上面我们模拟了“双向数据绑定”:父组件将数据传入子组件,子组件改变数据时通知父组件进行“同步更新”。但是要注意其实数据流向是单向的,即数据是父组件单向流入子组件,父组件数据的更新是通过子组件的事件通知以后才被更新。也就是说其实在Angular 2中:双向数据绑定 = 单向数据绑定 + 事件,以我们最熟悉的ngModel为例:

<input type='text' name='userName' [(ngModel)]="userName">

和下面的写法是等价的:

<input type='text' name='userName' [ngModel]="userName" (ngModelChange)="userName=$event">

同样的,如果将我们的child-component组件写作双向数据绑定的形式即为:

<child-component [(count)]='initialCount'></child-component>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
Feb 03 Javascript
jQuery实现html表格动态添加新行的方法
May 28 Javascript
jquery实现具有收缩功能的垂直导航菜单
Feb 16 Javascript
微信小程序实现实时圆形进度条的方法示例
Feb 24 Javascript
详解vue组件通信的三种方式
Jun 30 Javascript
jQuery实现新闻播报滚动及淡入淡出效果示例
Mar 23 jQuery
node基于puppeteer模拟登录抓取页面的实现
May 09 Javascript
利用vue重构有赞商城的思路以及总结整理
Feb 21 Javascript
vue视图不更新情况详解
May 16 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
Jan 21 Javascript
JavaScript仿京东秒杀倒计时
Mar 17 Javascript
JavaScript中作用域链的概念及用途讲解
Aug 06 Javascript
详解Angular之constructor和ngOnInit差异及适用场景
Jun 22 #Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 #Javascript
文本溢出插件jquery.dotdotdot.js使用方法详解
Jun 22 #jQuery
详解Vue 2.0封装axios笔记
Jun 22 #Javascript
EasyUI中的dataGrid的行内编辑
Jun 22 #Javascript
Ajax高级笔记 JavaScript高级程序设计笔记
Jun 22 #Javascript
vue 请求后台数据的实例代码
Jun 22 #Javascript
You might like
PHP 图片文件上传实现代码
2010/12/29 PHP
PHP文件去掉PHP注释空格的函数分析(PHP代码压缩)
2013/07/02 PHP
将word转化为swf 如同百度文库般阅读实现思路及代码
2013/08/09 PHP
PHP删除指定目录中的所有目录及文件的方法
2015/02/26 PHP
php实现word转html的方法
2016/01/22 PHP
phpStudy2016 配置多个域名期间遇到的问题小结
2017/10/19 PHP
用ADODB.Stream转换
2007/01/22 Javascript
List the Codec Files on a Computer
2007/06/18 Javascript
JavaScript CSS修改学习第一章 查找位置
2010/02/19 Javascript
javascript textarea光标定位方法(兼容IE和FF)
2011/03/12 Javascript
jquery结合CSS使用validate实现漂亮的验证
2015/01/29 Javascript
jQuery实现表单步骤流程导航代码分享
2015/08/28 Javascript
AngularJS 指令详细介绍
2016/07/27 Javascript
js完整倒计时代码分享
2016/09/18 Javascript
Jquery AJAX POST与GET之间的区别详细介绍
2016/10/17 Javascript
Node+Express+MongoDB实现登录注册功能实例
2017/04/23 Javascript
Javascript实现base64的加密解密方法示例
2017/06/27 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
2017/07/13 Javascript
[01:00:30]TFT vs VGJ.T Supermajor 败者组 BO3 第一场 6.5
2018/06/06 DOTA
[45:32]Liquid vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
用Python从零实现贝叶斯分类器的机器学习的教程
2015/03/31 Python
python 同时运行多个程序的实例
2019/01/07 Python
计算机二级python学习教程(3) python语言基本数据类型
2019/05/16 Python
python射线法判断一个点在图形区域内外
2019/06/28 Python
python基于paramiko将文件上传到服务器代码实现
2019/07/08 Python
Python数据相关系数矩阵和热力图轻松实现教程
2020/06/16 Python
记录模型训练时loss值的变化情况
2020/06/16 Python
python如何求圆的面积
2020/07/01 Python
西班牙土拨鼠床垫公司,感觉在云端:Marmota
2019/03/18 全球购物
比利时的在线灯具店:Lampen24.be
2019/07/01 全球购物
COSETTE官网:奢华,每天
2020/03/22 全球购物
俄罗斯建筑和装饰材料在线商店:Stroilandia
2020/07/25 全球购物
《果园机器人》教学反思
2014/04/13 职场文书
国旗下演讲稿
2014/05/08 职场文书
教师求职自荐信范文
2015/03/04 职场文书
房地产公司财务总监岗位职责
2015/04/03 职场文书