【问题标题】:How to automatically update Angular 6 component variables when a change to a different variable is detected?当检测到对不同变量的更改时,如何自动更新 Angular 6 组件变量?
【发布时间】:2018-10-11 20:21:33
【问题描述】:

我有一个生成白名单和黑名单的“标签”组件变量。目前,我有一个 updateTagLists() 函数,它将更新相应的白名单和黑名单,但我必须确保在必要时调用此函数,以便白名单/黑名单正确更新。这似乎违反直觉并且感觉不正确。当 this.tags 更改时,让 this.whitelist 和 this.blacklist 自动更新的正确方法是什么?下面发布的是我的组件。

import { Component, OnInit } from '@angular/core';

import { Tag } from '../../models/tag';
import { TagService } from '../../services/tag.service';

@Component({
  selector: 'app-admin',
  templateUrl: './admin.component.html',
  styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {
  tags: any;
  whitelist: Tag[];
  blacklist: Tag[];

  constructor(
    private tagService: TagService
   ) {}

  ngOnInit() {
    this.tagService.getTags(1).then((tags) => {
      this.tags = tags;
      this.updateTagLists
    });
  }

  updateTagLists() {
    this.whitelist = this.tags.filter((tag: Tag) => tag.isWhitelisted );
    this.blacklist = this.tags.filter((tag: Tag) => !tag.isWhitelisted );
  }

  whitelistAll() {
    // Todo: Is there a better way of doing this where we aren't specifying the exact keys needed?
    let updatedTags = this.tags.filter((tag) => !tag.isWhitelisted)
    updatedTags = updatedTags.map((tag) => {
      return { id: tag.id, name: tag.name, isWhitelisted: true, updated: true }
    });
    this.tags = updatedTags.concat(this.tags.filter((tag) => tag.isWhitelisted));
    this.updateTagLists();
  }

  blacklistAll() {
    // Todo: Is there a better way of doing this where we aren't specifying the exact keys needed?
    let updatedTags = this.tags.filter((tag) => tag.isWhitelisted);
    updatedTags = updatedTags.map((tag) => {
      return { id: tag.id, name: tag.name, isWhitelisted: false, updated: true }
    });
    this.tags = updatedTags.concat(this.tags.filter((tag) => !tag.isWhitelisted));
    this.updateTagLists();
  }

  handleToggle(event) {
    if (!event) return;
    let foundTag = this.tags.find( (tag) => event.id === tag.id );
    foundTag.isWhitelisted = !event.isWhitelisted;
    foundTag.updated = true;
    this.updateTagLists();
  }

}

【问题讨论】:

  • 当您在每个 Tag 上已经有一个 isWhitelisted 布尔值时,为什么会有两个不同的列表。我认为这应该足够了,您应该根据点击的标签之一来切换它。

标签: angular angular6


【解决方案1】:

最好的方法是只处理一个tags 数组,然后在此基础上做必要的事情。

我已经更新了你的 whiteListAllblackListAllhandleToggle 方法。

import { Component } from '@angular/core';
import { TagService } from './tag.service';

export interface Tag {
  id: number;
  name: string;
  isWhitelisted: boolean;
  updated: boolean;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  tags: Tag[];

  get whiteListedTags() {
    return this.tags.filter(tag => tag.isWhitelisted);
  }

  get whiteBlackTags() {
    return this.tags.filter(tag => !tag.isWhitelisted);
  }    

  constructor(private tagService: TagService) {}

  ngOnInit() {
    this.tagService.getTags(1).then((tags) => {
      this.tags = tags;
    });
  }

  whitelistAll() {
    this.tags = [...this.tags.map(tag => ({...tag, isWhitelisted: true, updated: true}))];
  }

  blacklistAll() {
    this.tags = [...this.tags.map(tag => ({...tag, isWhitelisted: false, updated: true}))];
  }

  handleToggle(index) {
    this.tags[index].isWhitelisted = !this.tags[index].isWhitelisted;
  }
}

在您的模板中,您可以通过检查 isWhitelisted 属性是否为 true 来检查 Tag 是否被列入白名单。

您也可以选择创建getters 来获取列入黑名单和列入白名单的标签,就像我在上面所做的那样。

这里有一个Sample StackBlitz 供您参考。

【讨论】:

  • 我喜欢你为 whitelistAll 和 blacklistAll 重构所做的一切。这清理了很多东西。谢谢!
  • 很高兴我能帮上忙。 :)
【解决方案2】:

而不是使用这样的函数:

updateTagLists() {
  this.whitelist = this.tags.filter((tag: Tag) => tag.isWhitelisted );
  this.blacklist = this.tags.filter((tag: Tag) => !tag.isWhitelisted );
}

只需像这样使用 2 个 TypeScript getter:

get whitelist() {
  return this.tags.filter((tag: Tag) => tag.isWhitelisted )
}

get blacklist() {
  return this.tags.filter((tag: Tag) => !tag.isWhitelisted )
}

您可以像这样在 HTML 中引用它们:

{{ whitelist | json }} {{ whitelist.length }}
{{ blacklist | json }} {{ blacklist.length }}

或者像这样在你的控制器中:

console.log(this.whitelist)
console.log(this.blacklist)

而且它们始终是 100% 准确的。无需担心在正确的时间调用函数来更新其值。

【讨论】:

  • PS 这里给出的其他答案也是正确的,并提供了一种使用 getter 和 setter 做完全相同的事情的替代方法
  • 这很完美,而且很干净。谢谢danday74!
【解决方案3】:

您可以在 tags 变量上使用 setter。

这是一个例子:

...

private _tags: any;

set tags(someTags: any) {
  this._tags = someTags;
  this.updateTagLists();
}

get tags(): any {
  return this._tags;
}

...

这将在值更新时运行 set 函数。 set 函数将设置一个保存当前标签值的私有变量,并将调用以更新其他列表。 getter 从私有 var 中获取值并返回它。

【讨论】:

    【解决方案4】:

    我不完全理解这个问题,但是如果您想对tags 的更改执行一些操作。然后为其创建一个 setter 函数,以便 this.tags 仅通过此函数进行更新。

    setTags(tags) {
       this.tags = tags;
       this.updateWhitelist();
       this.updateBlacklist();
    }
    

    从代码看来,标签只是从 onInit() 函数中得到改变。但是如果你想让标签作为 input() 那么

    private _tags;
    
    @Input()
    set tags(tags) {
       this._tags = tags;
       this.updateWhitelist();
       this.updateBlacklist();
    }
    
    get tags()  {
       return tags;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-13
      • 2023-03-05
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 2019-02-28
      • 2017-08-26
      • 1970-01-01
      相关资源
      最近更新 更多