最近到了新公司,用的技术是angular4,以前只用过angular1,本来以为两者差别不大,结果了解之后才知道两者是雷锋和雷峰塔的区别。发现两者除了都有名字叫angular之外,其它的地方我就呵呵了。工作学习了一段时间,我总结一些angular4的常用东西,希望有帮助到跟我一样的初学者。
今天要说的是组件交互,组件间的交互包括父子组件交互和一些非父子关系组件的交互。组件交互就是组件通过一定的方式来访问其他组件的属性和方法,从而来实现数据双向流动。组件交互有很多种方式可以选择,非父子关系的组件可以通过服务来实现数据的交互通信,我下面说的是具有父子关系的组件交互。
1.1 父组件向子组件传递数据
angular提供了输入(@Input)和输出(@Output)语法来处理组件数据的流入流出,这里的"输入",“输出”是以当前组件角度去说的。而父组件的数据是通过子组件的输入属性流入子组件,在子组件完成接收或拦截,以实现数据由上而下传递。举个列子,父组件的代码如下:
父组件模板引用子组件
// father template: ...
<children-error-code [errorCode] = "reErrorCode"></children-error-code>
其中"reErrorCode" 为父组件中的数据(这里假设为提示语"Oops,相关数据没有找到~~"的字符串),[errorCode] 为子组件的输入
子组件接收父组件的数据
在子组件中通过@Input装饰器进行数据接收,代码如下:
// children template: ...
<div>{{errorCode}}</div>
export class ChildrenComponent implements OnInt{
@Input() errorCode: string
}
在接收前,我们还可以对接收到的数据进行处理,这里我们可以使用setter拦截输入属性,一般来说getter和setter配套使用,对以上代码可以进行如下修改:
// children template: ...
<div>{{newString}}</div>
export class ChildrenComponent implements OnInt{
public newErrorCode: string = "";
@Input()
set newString(errorCode: string){//将接收到的数据重新处理后赋值给新值
this.newErrorCode = (errorCode === " "?"资料没有找到":errorCode);
}
get newString(){// get方法将新值返回给newString,所以页面绑定的是newString
return this.newErrorCode;
}
}
1.2 子组件向父组件传递数据
使用事件传递是子组件想父组件传递数据最常用的方式。子组件需要实例化一个用来订阅和触发自定义事件的EventEmitter类,这个实例对象是一个由装饰器@Output修饰的输出属性。父组件通过事件绑定的方式来订阅来自子组件触发的事件。
// 子组件传递数据给父组件
// children template: ...
<div (click) = "selectData()"></div>
export class ChildrenComponent implements OnInt{
@Output() selectChangeData: EventEmitter = new EventEmitter();
selectData(){
let dataPkg = { change: "true", data: data };
this.selectChangeData.emit(dataPkg);
}
}
上段代码中,子组件点击后向父组件传递了一个对象,那么子组件通过@Output将数据流向父组件,在父组件完成事件监听后做出响应,以此来实现子组件到父组件的数据交互。父组件代码如下:
// father template
<children-Item (selectChangeData)="selectChange($event)"></children-Item>
export class FatherComponent implements OnInt{
selectChange(data){
// 方法里面的参数data就是我们获取到的数据,这里可以对数据进行处理(TODO);
}
}
其他组件交互方式
上面说的两种方法都是通过输入输出属性绑定的方式来实现数据的双向流动。但是父组件仅仅是将数据源流向下级子组件,她不拥有读取子组件的相关成员变量和方法的权限。
1.通过局部变量实现数据交互
在Angular中的"模板局部变量",可以帮助我们获取子组件的实例引用,通过创建模板局部变量的方式,来实现父子组件的交互。即在父组件的模板中为子组件创建一个局部变量,那么这个父组件可以通过这个局部变量来获取子组件的公共成员变量和函数的权限。
父组件代码如下:
// father template
<children-Item (click)="collect.collectTheContact()" #collect></children-Item>
通过在父组件上绑定一个局部变量collect(以#号标记),以此来获取子组件类的实例对象。
子组件代码如下:
// children template
<div></div>
export class ChildrenComponent implements OnInt{
public detail:string = "";
collectTheContact(){
this.detail = "哈哈";
}
}
上述代码父组件通过模板局部变量的方法能够调用子组件的collectTheContact()方法,但是模板局部变量方法只能在模板中使用,而不能直接在父组件类里面使用,这里有一定的局限性。下面介绍一种更优雅的数据传递方式--@ViewChild,当父组件需要获取到子组件中的变量或者方法的时候,可以通过@ViewChild注入的方式来实现。逐渐中元数据ViewChild的作用是声明对子组件元素的实例引用,它提供了一个参数来选择将要引用的组件元素,这个参数可以是一个类的实例,也可以是一个字符串,它们实现的功能是一样的,只是表现的形式不同。
(1) 参数为类实例,表示父组件将绑定一个指令或者子组件实例
(2) 参数为字符串类型,表示将起到选择器的作用,即相当于在父组件中绑定一个模板局部变量,获取到子组件的一份实例对象的引用。
我们先来看上述的第二种情况(参数为字符串类型),和前面介绍的绑定模板局部变量是一样的,将上面父组件的代码进行修改;
父组件代码如下:
// father template
<children-Item (click)="collectList()" #collect ></children-Item>
export class FatherComponent implements OnInt{
@ViewChild('collect') collect;
collectList(){
this.collect.collectTheContact();//调用子组件的collectTheContact方法
}
}
参数为类实例对象,父组件代码如下:
// father template
<children-Item (click)="collectList()"></children-Item>
export class FatherComponent implements OnInt{
@ViewChild(ChildrenComponent ) childrenView: ChildrenComponent ;
collectList(){
this.childrenView.collectTheContact();//调用子组件的collectTheContact方法
}
}
上述知识点就更新到这里了,有什么问题或者疑问,欢迎交流