什么是 Angular 开发中的 Dumb components

Dumb components,在 Angular 开发中也被称为 Presentational components,它们的主要职责是通过展示数据和触发事件,把业务逻辑和 UI 表现分离开来。Dumb components 只通过 @Input() 接收数据,@Output() 向外发送事件,不负责处理任何业务逻辑,这些逻辑由 Smart components 或服务来承担。这是典型的单一职责原则的实现,能够提高代码的可维护性和可测试性。

Dumb components 的核心思想是让组件尽可能地简洁,只负责渲染自己所需的内容,以及通过输出事件来通知外界操作。这种组件完全与业务逻辑解耦,因此它们不依赖于业务状态的变化,只专注于 UI 的展示。当业务逻辑发生变化时,不需要对它们做任何改动。

使用 Dumb components 有几个好处:

  1. 提高代码复用性:因为这些组件只负责渲染 UI,所以可以在多个地方重用。
  2. 易于测试:由于没有业务逻辑,只需测试组件的输入输出和渲染结果即可。
  3. 易于维护:每个组件功能单一,当 UI 或业务逻辑变化时只需修改与之相关的组件,降低了出错的概率。

下面是一个简单的例子,通过具体代码来说明什么是 Dumb components 以及如何使用。

例子:一个用户卡片组件

我们要实现一个用户卡片组件,它只负责展示用户信息,并提供一个按钮来触发"删除"操作。所有的用户数据和删除操作的业务逻辑都在父组件中管理。

Step 1: 创建 Dumb 组件

首先我们创建一个 UserCardComponent,它接受用户数据并展示,同时提供一个输出事件。

typescript 复制代码
// user-card.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.css']
})
export class UserCardComponent {
  @Input() user: any;
  @Output() delete = new EventEmitter<void>();

  onDelete() {
    this.delete.emit();
  }
}
html 复制代码
<!-- user-card.component.html -->
<div class="user-card">
  <h3>{{ user.name }}</h3>
  <p>{{ user.email }}</p>
  <button (click)="onDelete()">Delete</button>
</div>

这里 UserCardComponent 仅负责展示用户信息,并且提供了一个 onDelete 方法来触发 delete 事件。组件的输入属性 user 是一个对象,包含用户的 nameemail 信息。

Step 2: 在父组件中使用 Dumb 组件

创建一个父组件 UserListComponent 来管理用户列表和删除操作。

typescript 复制代码
// user-list.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent {
  users = [
    { name: 'John Doe', email: 'john.doe@example.com' },
    { name: 'Jane Doe', email: 'jane.doe@example.com' }
  ];

  deleteUser(index: number) {
    this.users.splice(index, 1);
  }
}
html 复制代码
<!-- user-list.component.html -->
<div>
  <app-user-card
    *ngFor="let user of users; let i = index"
    [user]="user"
    (delete)="deleteUser(i)">
  </app-user-card>
</div>

UserListComponent 中,维护了一个用户数组 users。为了删除用户,我们定义了一个 deleteUser 方法,并在模板中通过 Angular 的 *ngFor 指令渲染多个 UserCardComponent。当 UserCardComponent 触发 delete 事件时,调用父组件的 deleteUser 方法进行相应处理。

Dumb 组件的进一步优化

为了更通用化和可维护,可以把输入数据的类型和输出事件的类型定义更加明确。

定义用户模型

typescript 复制代码
// user.model.ts
export interface User {
  name: string;
  email: string;
}

在组件中使用模型

typescript 复制代码
// user-card.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { User } from './user.model';

@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.css']
})
export class UserCardComponent {
  @Input() user: User;
  @Output() delete = new EventEmitter<void>();

  onDelete() {
    this.delete.emit();
  }
}

在父组件中使用模型

typescript 复制代码
// user-list.component.ts
import { Component } from '@angular/core';
import { User } from './user.model';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent {
  users: User[] = [
    { name: 'John Doe', email: 'john.doe@example.com' },
    { name: 'Jane Doe', email: 'jane.doe@example.com' }
  ];

  deleteUser(index: number) {
    this.users.splice(index, 1);
  }
}

通过这些步骤,我们实现了一个典型的 Dumb 组件。它只专注于展示用户信息,通过触发 delete 事件通知父组件,而父组件负责管理用户数据和删除操作的具体实现。

总结

Dumb components 是实现单一职责原则的关键,它们通过接收输入和发送输出事件,把业务逻辑和 UI 表现分离开来,提高了代码的复用性、可测试性和可维护性。通过上面的例子展示了在 Angular 中如何创建和使用 Dumb components,从而使应用程序更加模块化、结构清晰。

相关推荐
周亚鑫3 分钟前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
落魄小二12 分钟前
el-table 表格索引不展示问题
javascript·vue.js·elementui
y52364812 分钟前
Javascript监控元素样式变化
开发语言·javascript·ecmascript
Justinc.19 分钟前
CSS3新增边框属性(五)
前端·css·css3
fruge26 分钟前
纯css制作声波扩散动画、js+css3波纹催眠动画特效、【css3动画】圆波扩散效果、雷达光波效果完整代码
javascript·css·css3
neter.asia35 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫36 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
嚣张农民42 分钟前
JavaScript中Promise分别有哪些函数?
前端·javascript·面试
光影少年1 小时前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_1 小时前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习