【Angular教程】-组件通信|8月更文挑战

简介: 【Angular教程】-组件通信|8月更文挑战

引言:


上一篇我们初步了解的Angular中组件及基本的使用,但是所有的功能要是放到一个组件里面必然显得更加冗余,臃肿,我们通常会将组件按照一定的规则进行拆分,拆分后的组件免不了的就需要进行通信,这一篇我们就来一起熟悉一下Angular中的组件通信吧。


正文:


在实际的应用中我们的组件将会以树形的结构进行关联,所以组件间的关系主要就是:

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


准备一下我们的环境:

  1. 创建一个header组件: ng g c components/header
<app-button></app-button>
<app-title></app-title>
<app-button></app-button>
复制代码
export class HeaderComponent implements OnInit {
  constructor() {}
  ngOnInit(): void {}
}
  1. 创建一个title组件: ng g c components/title
<span>{{title}}</span>
export class TitleComponent implements OnInit {
  public title: string = '标题';
  constructor() {}
  ngOnInit(): void {}
}
  1. 创建一个button组件: ng g c components/button
<button>{{ btnName }}</button>
export class ButtonComponent implements OnInit {
  public btnName: string = '按钮';
  constructor() {}
  ngOnInit(): void {}
}


直接调用

适用于父子关系组件,注意点是直接调用使得父子组件的耦合性变高,要明确使用确实需要直接调用。

  1. 将我们的header组件挂载到app中,使得app和header之间形成父子组件关系
  2. 使用#为我们的组件起一个名称: <app-header #header></app-header>
  3. 现在我们的header组件还很空,我们扩展一下,要不然调用什么呢?
export class HeaderComponent implements OnInit {
  public name: string = 'HeaderComponent';
  printName(): void {
    console.log('component name is', this.name);
  }
}
  1. 组件扩展好以后我们就可以在父组件app中调用子组件header中的属性和函数了
<app-header #header></app-header>
<p>
  调用子组件属性: {{ header.name }}
  <button (click)="header.printName()">调用子组件函数</button>
</p>
  1. 第4步是在父组件的html模板中进行操作,有时候我们还需要在父组件的ts类中对子组件进行操作,我们接下来接着演示。
  2. 我们需要用到一个新的装饰器@ViewChild(Component)
export class AppComponent {
  title = 'angular-course';
  @ViewChild(HeaderComponent)
  private header!: HeaderComponent;
  // 声明周期钩子: 组件及子组件视图更新后调用,执行一次
  ngAfterViewInit(): void {
    // 调用子组件属性
    console.log(this.header.name);
    // 调用子组件函数
    this.header.printName();
  }
}


@Input和@Output

适用于父子关系组件

  1. 我们通过在header组件中定义title,来解耦title组件中直接调用导致扩展复杂的问题
  2. title组件中的title属性增加@Input()装饰器: @Input() public title: string = '标题';
  3. 为header组件新增title属性并赋值: public title: string = '我是新标题';
  4. 我们再header组件的html模板中这样来使用title组件: <app-title [title]="title"></app-title>
  5. 一起看看到现在的效果吧,界面虽然丑,但是下次使用组件时title设置是不是方便一点呢?

5.jpg

  1. 以上步骤实现了父组件的数据传递到了子组件中,那么我们接着来看子组件的数据怎么传递到父组件中呢? 我们一起来用@Output()装饰器实现以下吧
  2. title组件的ts类中增加titleChange属性: @Output() public titleChange = new EventEmitter();
  3. title组件的ts类中定时派发数据
ngOnInit(): void {
  // 定时将子组件的数据进行派发
  setInterval(() => {
    this.titleChange.emit(this.title);
  }, 1500);
}
  1. 现在我们来修改header父组件来接收派发来的数据:
<app-title 
  [title]="title" 
  (titleChange)="onChildTitleChange($event)">
</app-title>
onChildTitleChange(value: any) {
  console.log('onChildTitleChange: >>', value);
}


利用服务单利进行通信

适用于无直接关系组件

6.jpg

  1. 既然要通过服务来做通信,那我们就先创建一个服务吧: ng g s services/EventBus,并且我们声明了一个类型为Subject的属性来辅助通信
@Injectable({
  providedIn: 'root',
})
export class EventBusService {
  public eventBus: Subject<any> = new Subject();
  constructor() {}
}
  1. 我们为了省事就不重新创建组件了,因为我们的header中的按钮组件和title组件就符合没有直接关系的组件。
  2. 改造一下我们的button组件,并且添加点击事件来触发triggerEventBus函数
export class ButtonComponent implements OnInit {
  public btnName: string = '按钮';
  constructor(public eventBusService: EventBusService) {}
  ngOnInit(): void {}
  public triggerEventBus(): void {
    this.eventBusService.eventBus.next('我是按钮组件');
  }
}
  1. title组件中模拟数据的获取
export class TitleComponent implements OnInit {
  constructor(public eventBusService: EventBusService) {}
  ngOnInit(): void {
    this.eventBusService.eventBus.subscribe((value) => {
      console.log(value);
    });
  }
}


利用cookie、session或者localstorage进行通信

7.jpg

  1. 这个就很简单了,我们还是用title组件和button组件来做演示,这次我们在title组件中将数据保存,在button组件中获取数据。我们仅演示localstorage吧,其他都雷同的。
  2. title组件的ngOnInit()钩子中保存titlelocalstorage中: window.localStorage.setItem('title', this.title);
  3. 在button组件中获取数据: const title = window.localStorage.getItem('title');


结语:


本篇我们介绍了Angular的组件通信,为我们拆分后的组件可以进行合理的通信提供了保障,我们到现在组件的使用都是通过引入标签的方式进行,那还有其他的方式来使用我们的组件吗?当然,下一篇我们将一起来熟悉Angular中的动态组件。



相关文章
|
6月前
|
JavaScript
Angular使用@Input和@Output实现父子组件互相传参(类似Vue的props和this.emit)
Angular使用@Input和@Output实现父子组件互相传参(类似Vue的props和this.emit)
|
3月前
|
Java Spring
🔥JSF 与 Spring 强强联手:打造高效、灵活的 Web 应用新标杆!💪 你还不知道吗?
【8月更文挑战第31天】JavaServer Faces(JSF)与 Spring 框架是常用的 Java Web 技术。本文介绍如何整合两者,发挥各自优势,构建高效灵活的 Web 应用。首先通过 `web.xml` 和 `ContextLoaderListener` 配置 Spring 上下文,在 `applicationContext.xml` 定义 Bean。接着使用 `@Autowired` 将 Spring 管理的 Bean 注入到 JSF 管理的 Bean 中。
60 0
|
3月前
|
iOS开发 Android开发 MacOS
从零到全能开发者:解锁Uno Platform,一键跨越多平台应用开发的神奇之旅,让你的代码飞遍Windows、iOS、Android、macOS及Web,技术小白也能秒变跨平台大神!
【8月更文挑战第31天】从零开始,踏上使用Uno Platform开发跨平台应用的旅程。只需编写一次代码,即可轻松部署到Windows、iOS、macOS、Android及Web(通过WASM)等多个平台。Uno Platform为.NET生态带来前所未有的灵活性和效率,简化跨平台开发。首先确保安装了Visual Studio或VS Code及.NET SDK,然后选择合适的项目模板创建新项目。项目结构类似传统.NET MAUI或WPF项目,包含核心NuGet包。通过简单的按钮示例,你可以快速上手并构建应用。Uno Platform让你的技术探索之旅充满无限可能。
62 0
|
3月前
|
前端开发 UED
Angular 动画教程超赞!掌握让应用更具交互性的技巧,开启精彩的前端动画之旅!
【8月更文挑战第31天】在现代前端开发中,提升用户体验至关重要,而动画是增强应用交互性的有效手段。Angular 提供了强大的动画功能,可轻松添加各种动画效果。本文介绍了 Angular 动画的基本概念、使用动画模块、事件触发动画、动画序列与并行执行、性能优化及结合第三方动画库等最佳实践。通过遵循这些实践,可以充分发挥 Angular 动画的优势,提升用户体验。下面是一个简单的示例应用,展示了如何使用 Angular 动画实现元素的显示和隐藏效果。
52 0
|
3月前
|
JavaScript 测试技术
如何在 Angular 中使用 NgTemplateOutlet 创建可重用组件
如何在 Angular 中使用 NgTemplateOutlet 创建可重用组件
22 0
|
4月前
|
前端开发 JavaScript
前端框架与库 - Angular基础:组件、模板、服务
【7月更文挑战第16天】Angular,谷歌维护的前端框架,专注构建动态Web应用。组件是核心,包含行为逻辑的类、定义视图的模板和样式。模板语法含插值、属性和事件绑定。服务提供业务逻辑,依赖注入实现共享。常见问题涉及组件通信、性能和服务注入。优化通信、性能并正确管理服务范围,能提升应用效率和质量。学习组件、模板和服务基础,打造高效Angular应用。
63 1
|
5月前
|
JavaScript 小程序 API
技术经验分享:Angular动态创建组件之Portals
技术经验分享:Angular动态创建组件之Portals
|
6月前
快速创建Angular组件并定义传参、绑定自定义事件的方法
快速创建Angular组件并定义传参、绑定自定义事件的方法
|
6月前
Angular多个页面引入同一个组件报错The Component ‘MyComponentComponent‘ is declared by more than one NgModule怎么办?
Angular多个页面引入同一个组件报错The Component ‘MyComponentComponent‘ is declared by more than one NgModule怎么办?
|
JavaScript 定位技术
Angular1.x入门级自定义组件(导航条)
Angular1.x入门级自定义组件(导航条)