角度-同步内部和外部组件状态

时间:2018-12-04 01:17:55

标签: javascript angular angular-services angular-components

这个问题使我震惊,因为以前可能以另一种形式问过这个问题,但是我很难找到一个好的直接答案,所以我想问一下。

我正在构建一个具有许多组件的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)中的这种行为不太熟悉,并且会喜欢任何指针。

谢谢!

0 个答案:

没有答案