gpt4 book ai didi

angular - 如何对组件类应用单一职责?

转载 作者:行者123 更新时间:2023-12-03 21:22:16 26 4
gpt4 key购买 nike

我的问题有点简单。

假设我们有 2 个组件,每个组件都有自己的形式。

第一个组件:创建post.component.ts

第二部分:编辑-post.component.ts

当你创建 一个帖子,您只需填写该表单上的字段,如果一切都有效,您提交并创建该帖子(在某个内部数组中)。

当你编辑 一个帖子,您将特定的帖子对象加载到编辑组件中,然后编辑您需要的任何内容并提交。

现在,根据 单一职责 ,我们确实应该创建一个类来管理帖子创建和管理内部 UI 逻辑 该组件( edit-post.component.html )。

但是,我在许多示例中看​​到管理该案例的首选模式是使用 。 1 个表格 在编辑的情况下,他们只需保存 bool 值 当触发事件以通知特定监听器更改路由参数时设置。

如果该路由参数确实发生了更改,则有 If语句管理该特定逻辑(在 edit-form.component.ts 中实现的逻辑相同)。

让事件和监听器处理不同的目的似乎违反了单一责任。

这个例子很简单。在更高级的情况下,我们似乎可以非常快速地获得意大利面条代码。

如果我想坚持 Single 原则,实现这种情况的正确方法是什么?

最佳答案

我想就我认为非常有趣的这个问题添加我自己的想法。

Disclaimer: The code below doesn't tent to be a pure representation of SOLID in Angular but at least get close up to Single Responsability & Open-Close principles.I am totally open to any constructive comment and it would be great to have a look into another approaches.


尽管大小在 Web 应用程序中很重要,但我们可以实现 single responsability & Open-close不会过多影响我们的捆绑包大小的原则。
按照问题中建议的示例,我们可以有一个 user-form.component.ts 只处理主要/通用逻辑,例如表单组和所有验证。
// user-form.component.ts
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (submit)="submit.next($event)">
<label>Username</label>
<input type="text" formControlName="username" />
<label>Password</label>
<input type="password" formControlName="password" />
<!-- ... -->
<button type="submit" > Save </button>
</form>
`
})
export class UserFormComponent {
@Input() set user(user: User) {
this.userForm.patchValue({...user})
}

@Output() submit = new EventEmitter<User>();

userForm = new FormGroup({
username: new FormControl('', [Validators.Required, UserNameValidator]),
password: new FormControl('', [Validators.Required, PasswordValidator]
// ...
})
}
那么没关系被一个 edit-user-dialog.component.ts包裹, add-user.component.ts等每个包装器可以以不同的方式管理它。
前任:
<app-user-form [user]="user" (submit)="edit($event)">
</app-user-form>
<app-user-form (submit)="add($event)">
</app-user-form>
如果我们从 user 点开始组件托管在其自己的模块中我不认为分解该表单及其包装器会增加太多捆绑包大小。
开关
有时需求(设计,用例......)通过添加标志(例如具有不同标签的提交按钮)来强制使 user-form.component.ts 更大。
只要有可能,我们就必须避免使用这些标志。
不要这样做:
// user-form.component.ts
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (submit)="submit.next($event)">
<label>Username</label>
<input type="text" formControlName="username" />
<label>Password</label>
<input type="password" formControlName="password" />
<!-- ... -->
<button type="submit" > {{ mode === 'edit' ? 'Edit' : 'Add' }} </button>
</form>
`
})
export class UserFormComponent {
@Input() set user(user: User) {
this.userForm.patchValue({...user})
}
@Input() mode : 'edit' | 'add';
@Output() submit = new EventEmitter<User>();

userForm = new FormGroup({
username: new FormControl('', [Validators.Required, UserNameValidator]),
password: new FormControl('', [Validators.Required, PasswordValidator]
// ...
})
}
做:
// user-form.component.ts
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (submit)="submit.next($event)">
<label>Username</label>
<input type="text" formControlName="username" />
<label>Password</label>
<input type="password" formControlName="password" />
<!-- ... -->
<button type="submit" > {{ submitLabel }} </button>
</form>
`
})
export class UserFormComponent {
@Input() set user(user: User) {
this.userForm.patchValue({...user})
}
@Input() submitLabel = 'Save';
@Output() submit = new EventEmitter<User>();

userForm = new FormGroup({
username: new FormControl('', [Validators.Required, UserNameValidator]),
password: new FormControl('', [Validators.Required, PasswordValidator]
// ...
})
}
<app-user-form [user]="user"
[submitLabel]="'Edit'"
(submit)="edit($event)">
</app-user-form>
<app-user-form  [submitLabel]="'Add'"
(submit)="add($event)">
</app-user-form>
这种方法特别允许我们提供默认翻译,或使用自定义翻译而不触及原始 user-form.component.ts
但是在其他情况下,设计或要求更具体,那么,我们被迫寻找优雅或复杂的解决方案。例如,在某些情况下,我们必须隐藏输入或添加额外的验证。
一种方法是将 user-form.component.ts 分解成小块(form-field-component.ts)并将内容投影到 user-form.component 中。
// user-form.component.ts
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (submit)="submit.next($event)">
<ng-content></ng-content>
</form>
`
})
export class UserFormComponent implements IUserFormComponent {
private value: User;
@Input() set user(user: User) {
this.value = user;
this.userForm.patchValue({...user})
}
@Output() submit = new EventEmitter<User>();

// IUserForm
userForm = new FormGroup({
username: new FormControl('', [Validators.Required, UserNameValidator]),
password: new FormControl('', [Validators.Required, PasswordValidator]
// ...
})


reset() {
this.user = this.value;
}
}
// user-form-n-field.component.ts
@Component({
selector: 'app-user-n-field',
template: `
<label> {{ usernameLabel }} </label>
<input [control]="control" />
`
})
export class UserFormNFieldComponent {
@Input() label = 'n';

control: AbstractControl;

constructor(userFormComponent: IUserFormComponent) {
this.control = this.userFormComponent.userForm.controls.n;
// maybe subscribe the userForm changes
// or add extra validations
}
}
最终的用法可能如下所示:
<app-user-form #form [user]="user" 
(submit)="edit($event)">
<!-- ... -->
<app-user-form-avatar-field></app-user-form-avatar-field>
<app-user-form-username-field></app-user-form-username-field>
<app-user-form-password-field></app-user-form-password-field>
<!-- ... -->
<button type="button" (click)="form.reset()" >Reset</button>
<button type="submit" >Edit</button>
</app-user-form>
<app-user-form [user]="user"
(submit)="add($event)">
<app-user-form-username-field></app-user-form-username-field>
<app-user-form-enabled-field></app-user-form-enabled-field>
<!-- ... -->
<button type="submit" >Add</button>
</app-user-form>

关于angular - 如何对组件类应用单一职责?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50863564/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com