这个问题使我震惊,因为以前可能以另一种形式问过这个问题,但是我很难找到一个好的直接答案,所以我想问一下。
我正在构建一个具有许多组件的Angular应用程序,它们既应能够控制自己的内部状态(如果未连接到某些全局或局部状态),又可以从外部数据接收其状态。
为澄清起见,让我举一个例子。我有一个页面,其中显示了一组过滤器,这些过滤器可过滤内容数组(在其他位置)。过滤器采用多种形式,其中之一就是复选框。
因此,我构建了一个如下所示的复选框组件:
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
/** A simple styled checkbox component, which emits on change. */
@Component({
selector: 'app-checkbox',
templateUrl: './checkbox.component.html',
styleUrls: ['./checkbox.component.scss']
})
export class CheckboxComponent implements OnInit {
/** Label to apply to checkbox in HTML */
@Input() public name = '';
/** Whether the checkbox is disabled (non-clickable). */
@Input() public disabled = false;
/** Any additional CSS class to apply. */
@Input() public class = '';
/** Function called on click. Fed object with checkbox name and value. */
@Output() change = new EventEmitter();
/** Whether the checkbox is checked. */
@Input() checked = false;
constructor() { }
ngOnInit() {}
/** Selects or deselects the checkbox on click. */
onClick() {
this.checked = !this.checked;
this.change.emit({ checked: this.checked, name: this.name });
}
}
我认为HTML不会有太大帮助。我在大多数地方使用此组件,方法是根据来自共享服务的外部值(或父组件数据)传入其checked
值,并在单击时更新传递的数据。
我有两个问题:
尽管该复选框仅可能在外部读取其值的情况下使用,但我目前还在组件“库”中使用它,该组件仅显示UI交互,因此理想情况下,让组件(和其他组件)能够在未传递更改功能的情况下进行自身切换(因此this.checked = !this.checked
)。但是,如果我这样做,则该复选框checked
的值将成为两个事实来源–其自身的内部状态,以及change
函数已更改的任何外部状态(非库上下文)。 如何创建一个调用change
函数的组件,如果没有,该组件如何在内部处理它的类?我遇到了麻烦,特别是检测这种函数是否具有被传递了,尽管我想我可以传递一个附加的布尔属性,但这似乎是重复和混乱的。
我遇到了以下问题:当相关服务数据发生更改时,组件似乎没有更新。具体来说,我在两个单独的模式中拥有相同的过滤器复选框,如果在一个模式中进行更改,它将更改另一个模式,但是当我转到另一个模式并将其更改回时,更改不会同步到另一个(原始)模式。在我看来,该组件从安装时的服务 (例如,模态的安装)接收其值,但它不侦听数据更改并做出相应的反应。 (这里的假设是模态似乎没有完全卸载)。但总的来说,我不确定这是如何工作或应该如何工作。 如何使Angular组件“监听”服务数据的变化?
我的FiltersService
在下面,以让您了解我如何回答此问题:
import { Injectable } from '@angular/core';
export interface Filter { name: string; value: any; }
/** Tracks and updates status of car filters throughout application. */
@Injectable({
providedIn: 'root'
})
export class FiltersService {
/** Object of filters, with name pointing to value (any). */
filters: object = {};
constructor() { }
/** Sets an object of filters (one or more) at once. */
set(filters: object) {
this.filters = Object.assign(this.filters, filters);
return this.filters;
}
}
任何我在做什么错的感觉都阻止了组件对服务数据更改做出反应?这是我如何渲染组件的示例(setLocalFilters
更改父组件本地的对象,然后在提交时更新服务),localFilters
基本上是全局过滤器服务数据的副本,我已经验证了,符合我的预期:
<app-checkbox
name={{option}}
(change)="setLocalFilter($event.name, $event.checked)"
[checked]="localFilters[option]"
></app-checkbox>
我了解服务/组件应如何正确交互吗?对Angular(或Angular)中的这种行为不太熟悉,并且会喜欢任何指针。
谢谢!