如下的测试例子均可以在 github 找到,可是最近好像不太稳定。javascript
其实 ng2 在这方面作得挺好的,用起来也很简单,因此看完基本就能够动手写一写。强大并不止是这一方面,在写这些的过程当中,经过一些配置,让开发很纯粹,有时间再录一个新手入门的开发教程。css
这种方式是最简单的,在 ng2
中处理得很是完美,经过在子组件中标记 @Input()
输入接口的方式进行接收父组件的值,我下面的 demo 主要分了几种场景,尽量的多覆盖不一样状况吧。html
基本上例子中覆盖了常见的状况:java
直接传入一个字符串的状况,不须要绑定父组件的一个变量git
绑定父组件变量的状况,而后能够在父组件中不断修改github
输入别名的状况,能够在子组件中对输入的变量名进行从新设置typescript
ngOnChanges()
在子组件中监听属性的修改app
特殊状况下,咱们须要对父组件传入的数据进行过滤dom
@ViewChild()
注解的跨多层子组件的观察方式函数
说了这么多,来看一下实际的代码吧。
// Parent component import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.css'] }) export class ParentComponent implements OnInit { baby: string = '你的名字'; constructor() { } ngOnInit() { } }
// Parent html <h3>请输入 Baby 的名字:</h3> <input [(ngModel)]="baby" type="text"> <app-child babyName="hello" [inputBabyName]="baby" aliasBabyName="我是别名"></app-child>
// Child component import { Component, OnInit, Input, SimpleChange } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'] }) export class ChildComponent implements OnInit { @Input() babyName: string; @Input() inputBabyName: string; @Input('aliasBabyName') aliasName: string; changes: string; constructor() { } ngOnInit() { } ngOnChanges(changes: SimpleChange) { this.changes = JSON.stringify(changes); } }
// Child html <h3>我是子组件的属性(babyName) => {{babyName}}</h3> <h3 style="color:red;">我是跟父组件来:{{inputBabyName}}</h3> <h3>我是 aliasBabyName => aliasName:{{aliasName}}</h3>
那么我须要过滤一下值要怎么弄呢?
这样咱们就能够用到 setter 和 getter 的特性来作,具体以下:
// Child component _filterName: string = ''; @Input() set filterName(n: string) { this._filterName = n + 'wowo~~~'; } get filterName() { return this._filterName; }
// Parent html <app-child [filterName]="babyName"></app-child>
这个其实也是用 @Input()
这个注解来作的,有点相似 computed
的概念吧,可是这样作对于习惯 Java 的小伙伴是很友好的,其实经过一些权限的设置,还可以更加的强大。
@ViewChild() 的方式
这种方式我以为更多的是,个人沟通逻辑存在于 TS
中的时候就很实用。而且是描述性的定义方式,因此逻辑也是清晰的。
// Parent component // 方式1,定义了 `#` 的钩子也是能够引用的 @ViewChild('child') cc: ChildComponent; // 直接观察某一个子组件 @ViewChild(ChildComponent) cc_other: ChildComponent; // 调用的时候 this.cc.name = '变身啦!超级赛亚人'; this.cc_other.name = '变身啦!超级赛亚人 4';
能够思考一下,是否任何形式的父组件流入子组件的方式,均可以触发
ngOnChanges()
方法。
从软件的结构上来说,是上层抽象对底层的具体实现是隐藏的,因此具体层的东西最好尽量少的知道抽象层的事情,也许表达方式不同,可是这样的话封闭性会好不少,更多的暴露是以某一个权限开放的接口形式。可是通讯是很复杂的东西,就好像人与人之间的联系是同样的。好吧,咱们来具体说一会儿组件怎么访问父组件。主要经过的方式是:
在子组件定义一个 @Output()
的 EventEmitter<T>
对象,这个对象能够是 Subject 的形式存在,也就是可使用 RxJS 的思想来作,其中 T
范型表示定义须要传入的数据具体类型。
父组件中定义一个本身的函数来修改自身的信息,或者再传入其余子组件使用。
// Parent component import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.css'] }) export class ParentComponent implements OnInit { babyName: string; constructor() { } ngOnInit() { this.babyName = '小撸一号'; } changeBabyName(newBabyName) { this.babyName = newBabyName; } }
// Parent html <h3>BabyName:{{babyName}}</h3> <app-child (changeBabyName)="changeBabyName($event)"></app-child>
import { Component, OnInit, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'] }) export class ChildComponent implements OnInit { @Output() changeBabyName: EventEmitter<string> = new EventEmitter<string>(); rhashcode = /\d\.\d{4}/; constructor() { } ngOnInit() { } getNewBabyName(e) { let newName = this.makeHashCode('小撸新号'); this.changeBabyName.next(newName); } /* UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript */ makeHashCode(prefix) { prefix = prefix || '60sky'; return String(Math.random() + Math.random()).replace(this.rhashcode, prefix); } }
<button (click)="getNewBabyName($event)">我要改我本身的名字</button>
其中须要注意的是父组件中方法注入的 $event
对象,这个对象在这里注入的是子组件传入的值,因此在父组件中就能够直接使用了,我这里定义了 string 类型的数据,因此传入后定义接口的参数类型也是相对应的。
ng2 在无关组件的处理上,真的处理得很干脆,给你一个钩子,你用吧!就是这种简单的思路。这里我只介绍部分,由于官方文档有更加详细的介绍,否则我这篇文章就写得太长了~由于方式有不少种,发挥小聪明就能发现不少。
事件回调传来传去的方式
Service 的注入
#
钩子的方式
这里介绍的是一个 #
钩子的方式来作,直接来代码吧,很方便的。
其中,须要注意的是做用域的隔离,子组件能够很好的隔离做用域。
// Parent component import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.css'] }) export class ParentComponent implements OnInit { babyName: string = '小撸一号'; constructor() { } ngOnInit() { } }
// Parent html <input [(ngModel)]="babyName" type="text"> <app-child #child [childName]="babyName"></app-child> <app-otherChild helloBaby="child.childName"></app-otherChild>
// Child component import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'] }) export class ChildComponent implements OnInit { @Input() childName: string; constructor() { } ngOnInit() { } }
<h3 style="color:red;">Child:{{childName}}</h3>
// OtherChild component import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-otherChild', templateUrl: './otherChild.component.html', styleUrls: ['./otherChild.component.css'] }) export class OtherChildComponent implements OnInit { @Input() helloBaby: string; constructor() { } ngOnInit() { } changeChildName(e) { this.helloBaby = '小撸新号'; } }
// OtherChild html <h3 style="color:blue;">otherChild:{{helloBaby}}</h3> <button (click)="changeChildName($event)">我来统一修改一下</button>
其实还有一些方式和特殊场景下的处理,因此整体来讲,ng2 在这方面是不错的~