Angular6 学习笔记——组件详解之组件通讯

angular6.x系列的学习笔记记录,仍在不断完善中,学习地址:

系列目录

(1)组件详解之模板语法

(2)组件详解之组件通讯

(3)内容投影, ViewChild和ContentChild

(4)指令

(5)路由

章节目录

1 前言

2 Angular组件间的通讯

2.1. 父子组件间的通讯

  • 父组件设置子组件属性

  • 父组件调用子组件事件

  • 子组件向父组件发射事件

2.2 非父子组件通讯

  • Service

  • 路由传值

  • 传递一个值

  • 传递一个对象

3 通用方式实现通讯

  • localStorage

  • 服务端

1前言

前端框架,例如extjs,vue,angular等,都是或趋于组件化,所以组件间的通讯,是一个亟需解决的问题
一般而且言,这些组件之间都会形成这种树形结构
在这里插入图片描述
组件之间会有下列3种关系:

  1. 父子关系
  2. 兄弟关系
  3. 没有直接关系

通常采用下列方式处理(某些方式是框架特有)组件间的通讯,如下:

  1. 父子组件之间的交互(@Input/@Output/模板变量/@ViewChild)
  2. 非父子组件(Service/localStorage)
  3. 还可以利用Session等服务器端的解决方法

2Angular组件间的通讯

2.1父子组件之间的通讯

在父子组件之间通讯:

  • @Input:是属性绑定,父组件向子组件传递数据 @Input讲解及用法

  • @Output:是事件绑定,子组件向父组件传递数据的同时触发事件

2.1.1在父组件设置子组件上面的的属性

通过@input绑定子组件的属性,注意属性得是公开public的,私有private属性是无法传递的
es6新语法get/set.为属性提供了一个方便习惯的读/写方式, 拦截属性的存取行为。
在父组件设置该属性,就能够通过set方法来修改,从而实现在父组件设置子组件属性
代码如下

子组件模板文件

 <h1>{{childTitle}}</h1>

子组件Ts文件

import { Component, OnInit, Input } from '@angular/core';
  
  @Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.sass']
  })
  export class ChildComponent implements OnInit {
  
   private _childTitle: string = '子组件标题';
 
   @Input()
   set childTitle(childTitle: string) {
     this._childTitle = childTitle;
   }
   get childTitle(): string {
     return this._childTitle;
   }
 
   constructor() { }
 
   ngOnInit() {
 
   }
 }


 

父组件模板文件

<p>
  parent-and-child works!
 </p>
 <app-child childTitle="可设置子组件标题"></app-child>

父组件Ts文件

import { Component, OnInit } from '@angular/core';
  
  @Component({
    selector: 'app-parent',
    templateUrl: './parent-and-child.component.html',
    styleUrls: ['./parent-and-child.component.sass']
  })
  export class ParentAndChildComponent implements OnInit {
  
   constructor() { }
 
   ngOnInit() {
 
   }
 
 }

2.1.2父组件直接调用子组件的方法

通过模板内部定义子组件变量,在父组件上可以直接调用子组件的方法,如下:

子组件模板文件

<p>child work</p>

子组件Ts文件

import { Component, OnInit, Input } from '@angular/core';
  
  @Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.sass']
  })
  export class ChildComponent implements OnInit {
   constructor() { }
 
   ngOnInit() {
 
   }
 
   childPrint() {
     alert("来自子组件的打印");
   }
 }

父组件模板文件

<p>
   parent-and-child works!
 </p>
 <app-child #child></app-child>
 <button (click)="child.childPrint()"></button>

父组件Ts文件

import { Component, OnInit } from '@angular/core';
  
  @Component({
    selector: 'app-parent',
    templateUrl: './parent-and-child.component.html',
    styleUrls: ['./parent-and-child.component.sass']
  })
  export class ParentAndChildComponent implements OnInit {
  
   constructor() { }
 
   ngOnInit() {
 
   }
 
 }

2.1.3父组件接受子组件派发的事件

通过@Output在子组件绑定一个事件发射器,在父组件通过事件绑定监听该事件
这样在子组件派发一个事件,父组件就能够收到

子组件模板文件

<p>child work</p>

子组件Ts文件

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
  
  
  @Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.sass']
  })
  export class ChildComponent implements OnInit {
 
   @Output()
   initEmit = new EventEmitter<string>();
 
   constructor() { }
 
   ngOnInit() {
     this.initEmit.emit("子组件初始化成功");
   }
 }

父组件模板文件

<p>
   parent-and-child works!
 </p>
 <app-child (initEmit)="accept($event)"></app-child>

父组件Ts文件

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
  
  @Component({
    selector: 'app-parent',
    templateUrl: './parent-and-child.component.html',
    styleUrls: ['./parent-and-child.component.sass']
  })
  export class ParentAndChildComponent implements OnInit {
  
   constructor() { }
 
   ngOnInit() {
     
   }
   accept(msg:string) {
     alert(msg);
   }
 }

2.2没有直接关系的组件

2.2.1service

做一个全局单例的service,然后多个组件共享这个实例,当然就可以共享其中的成员,来进行通讯
在这里插入图片描述
具体代码如下

service文件

import { Component, Injectable, EventEmitter } from '@angular/core';
 @Injectable()
 export class myService {
   public info:string = '';
   constructor() {}
 }

在app.module.ts文件的providers里添加这个服务

组件1的模板文件

<p>child1 work</p>
 
 <button (click)="showInfo()"></button>

组件1的TS文件

import { Component, OnInit} from '@angular/core';
 import { myService } from '../../../service/myService..service';
  
  
  @Component({
    selector: 'app-child',
    templateUrl: './child1.component.html',
    styleUrls: ['./child1.component.sass']
 })
 export class Child1Component implements OnInit {
 
   constructor(
     public service: myService
   ) { }
 
   ngOnInit() {
     
   }
   showInfo() {
     alert(this.service.info);
   }
 }

组件2的模板文件

<p>
   child2 works!
 </p>
 <button (click)="changeInfo()"></button>

组件2的TS文件

import { Component, OnInit} from '@angular/core';
  import { myService } from '../../service/myService..service';
  
  @Component({
    selector: 'app-child2',
    templateUrl: './child2.component.html',
    styleUrls: ['./child2.component.sass']
  })
  export class Child2Component implements OnInit {
 
   constructor(
     public service: myService
   ) { }
 
   ngOnInit() {
 
   }
   changeInfo() {
     this.service.info = this.service.info + "1234";
   }
 }

2.2.2路由传值

对于2个不同路由的组件,我们也可以通过路由传递信息
假设2个路由分别为/home,/about
补充下述代码路由的引用

 import { Router } from '@angular/router';
 import { ActivatedRoute, Params } from '@angular/router';
 
   constructor(
     private router: Router,
     private route: ActivatedRoute,
   ) { }
 

2.2.2.1传递一个值
假如从/home路由向/about路由传递一个字符串或数字

1先把/about的路由地址改为/about/:id, (:id 是一个路由参数的令牌(Token),比如~/home/42 这个URL中,“42”就是id参数的值)
2在/home写上路由跳转且传值的连接

 <button [routerLink]="['/about',1]">跳转</button>
 <button [routerLink]="['/about',"home"]">跳转</button>

3在跳至的页面~/about接受传入的值

   id: string = '';
 
   ngOnInit() {
     //获取传入的值
     this.id = this.route.snapshot.params['id'];
   }

2.2.2.2传递一个对象
类似于上述的传递一个值,但是不需要再路由末尾加上/:id

代码也有些不同

this.router.navigate([’/about’], {
queryParams: {
id: ‘1’,
status: true
}
});

接受传入的对象

 id: number = 0;
   status: boolean = false;
   ngOnInit() {
     this.route.queryParams
       .subscribe((params: Params) => {
         this.id = params['id'];
         this.status = params['status'];
       })
   }

3、通用方式实现通讯

3.1 localstorage处理

在angular中也可以使用本地存储这种比较通用的方式在组件间通讯,但本地存储有下列弊端:

  1. 存储空间有限
  2. 只能存储字符串

在这里插入图片描述
具体的实现代码如下

组件1的Ts的文件

import { Component, OnInit } from '@angular/core';
  
  @Component({
    selector: 'app-child1',
    templateUrl: './child1.component.html',
    styleUrls: ['./child1.component.sass']
  })
 export class Child1Component implements OnInit {
 
   constructor() { }
 
   ngOnInit() {
 
   }
 
    setData(){
     window.localStorage.setItem("test", JSON.stringify({ key: 'test', value: 1 }));
   }
 }

组件2的Ts的文件

import { Component, OnInit } from '@angular/core';
  
  @Component({
    selector: 'app-child2',
    templateUrl: './child2.component.html',
    styleUrls: ['./child2.component.sass']
  })
  export class Child2Component implements OnInit {
  
   constructor() { }
 
   ngOnInit() {
 
   }
 
    getData() {
     var json = window.localStorage.getItem("test");
     var obj = JSON.parse(json);
     console.log(obj.key);
     console.log(obj.value);
   }
 }

3.2 服务端处理

也可以在服务端来处理组件间的通讯问题,这是一个思路,但是已经脱离讨论的主题,就不赘述

(终)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值