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 相关文章推荐
在IE下获取object(ActiveX)的Param的代码
Sep 15 Javascript
JS随机生成不重复数据的实例方法
Jul 17 Javascript
JS无限极树形菜单,json格式、数组格式通用示例
Jul 30 Javascript
JavaScript编写Chrome扩展实现与浏览器的交互及时间通知
May 16 Javascript
微信小程序  modal弹框组件详解
Oct 27 Javascript
Vue项目自动转换 px 为 rem的实现方法
Oct 29 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 Javascript
使用apifm-wxapi模块中的问题及解决方法
Aug 05 Javascript
Vue.js中provide/inject实现响应式数据更新的方法示例
Oct 16 Javascript
vue 实现tab切换保持数据状态
Jul 21 Javascript
解决vue-cli输入命令vue ui没效果的问题
Nov 17 Javascript
详解Vue的options
May 15 Vue.js
详解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实现克鲁斯卡尔算法实例解析
2014/08/22 PHP
PHP仿微信发红包领红包效果
2016/10/30 PHP
详解Laravel服务容器的绑定与解析
2019/11/05 PHP
Ext JS Grid在IE6 下宽度的问题解决方法
2009/02/15 Javascript
JavaScript中获取元素索引的函数
2010/09/10 Javascript
jquery实现心算练习代码
2010/12/06 Javascript
放弃用你的InnerHTML来输出HTML吧 jQuery Tmpl不详细讲解
2013/04/20 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
javascript处理a标签超链接默认事件的方法
2015/06/29 Javascript
JavaScript实现带箭头标识的多级下拉菜单效果
2015/08/27 Javascript
jQuery实现选项联动轮播效果【附实例】
2016/04/19 Javascript
基于BootStrap Metronic开发框架经验小结【七】数据的导入、导出及附件的查看处理
2016/05/12 Javascript
jQuery时间日期三级联动(推荐)
2016/11/27 Javascript
vue兄弟组件传递数据的实例
2018/09/06 Javascript
微信小程序实现选项卡效果
2018/11/06 Javascript
vue+iview动态渲染表格详解
2019/03/19 Javascript
解决layui富文本编辑器图片上传无法回显的问题
2019/09/18 Javascript
vue data对象重新赋值无效(未更改)的解决方式
2020/07/24 Javascript
jQuery实现全选按钮
2021/01/01 jQuery
举例简单讲解Python中的数据存储模块shelve的用法
2016/03/03 Python
浅谈编码,解码,乱码的问题
2016/12/30 Python
python的dataframe和matrix的互换方法
2018/04/11 Python
python调用OpenCV实现人脸识别功能
2018/05/25 Python
Python常见数字运算操作实例小结
2019/03/22 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
Python使用Pyqt5实现简易浏览器(最新版本测试过)
2020/04/27 Python
python--shutil移动文件到另一个路径的操作
2020/07/13 Python
adidas澳大利亚官方网站:adidas Australia
2018/04/15 全球购物
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
Shop Apotheke瑞士:您的健康与美容网上商店
2019/10/09 全球购物
请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值
2014/09/15 面试题
中英文求职信范文
2015/03/19 职场文书
2015年材料员工作总结
2015/04/30 职场文书
公司员工管理制度
2015/08/04 职场文书
四年级语文教学反思
2016/03/03 职场文书
Nest.js参数校验和自定义返回数据格式详解
2021/03/29 Javascript