【问题标题】:Angular 2 refreshing the view without route.navigateAngular 2 在没有 route.navigate 的情况下刷新视图
【发布时间】:2016-07-31 20:28:40
【问题描述】:

我已经构建了一个与 REST api 通信的 CRUD 应用程序,但没有找到在删除一个项目后刷新视图的方法。我过去曾使用 router.navigate 在其他方法(例如 create 方法)之后更改视图,并且效果很好。

问题是调用 delete 方法的事件在同一个项目列表中(每个 *ngFor 项目都有自己的删除事件)。因此,如果我删除一个项目,然后我使用 router.navigate 转到当前视图,它什么也不做,因为您已经在那里,因此即使它已经工作,也看不到没有删除项目的视图的更新版本。

有没有其他方法可以在不使用 route.navigate 的情况下刷新视图?

编辑:

我已经尝试实现 ChangeDetectorRef,但仍然无法正常工作...

这是组件:

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { ApiNoticiasService } from './api-noticias.service';
import { ROUTER_DIRECTIVES } from '@angular/router';

@Component({
  moduleId: module.id,
  selector: 'app-noticias',
  templateUrl: 'noticias.component.html',
  styleUrls: ['noticias.component.css'],
  directives: [ROUTER_DIRECTIVES],
  providers: [ApiNoticiasService]
})
export class NoticiasComponent implements OnInit {
  noticias: any;

  constructor(
    private cd: ChangeDetectorRef,
    private _apiNoticias: ApiNoticiasService) { }

  ngOnInit() {
    this._apiNoticias.getNoticias()
      .then( (noticias) => this.noticias = noticias)
      .catch((err) => {
        console.log(err);
      });
  }

  deleteNoticia(id){
    this._apiNoticias.deleteNoticia(id)
      .catch((err) => {
      console.log(err);
      });
    this.cd.markForCheck();
  }

}

这是服务中的方法:

deleteNoticia(id) {
    return this._http.delete('http://localhost:3000/noticias/' +id)
      .map((response: Response) => response.json())
      .toPromise()
      .catch((err: any) => {
        console.log(err); 
        return Promise.reject(err);
      });
  }

【问题讨论】:

  • 能否请您为 REST 通信服务和您要刷新的组件添加代码。

标签: angular angular2-router


【解决方案1】:

您正在寻找的主题是变更检测。官方文档似乎还没有多说,但this blog post 对此进行了相当深入的解释。

我猜您正在使用推送更改检测,因为默认值会检查每个事件的所有内容,并且应该已经自动捕获您的删除。您可以放弃它并恢复默认设置,但您会失去希望从该设置中获得的任何性能提升。

为了继续进行推送更改检测,与您的问题相关的部分大约位于页面下方的 3/4。您需要在显示该项目的组件中注入ChangeDetectorRef,并在删除发生时对其调用markForCheck()

编辑: 在查看您的代码时,您的问题实际上是您实际上并没有更新视图中的数据。服务器可能已经删除了该项目,但客户端的本地副本仍然存在。

您将需要通过适当更改 noticias 手动删除本地数据,或者从服务器重新获取整个批次并用新获取的结果替换本地缓存,就像在 ngOnInit 中所做的那样.后一个选项必须在删除承诺的.then() 内完成,否则获得正确的结果将受制于竞争条件。

【讨论】:

  • 我很确定我没有以正确的方式实现它。还是不行……
  • @cerealex 原来你根本没有使用推送更改检测。查看我的编辑。
  • 我试图在视图中使用 *ngIf="deleted==noticia.id" ,然后在删除方法的末尾让 deleted = id ,这样它就不会了dom,但似乎 *ngIf 在呈现后并没有继续收听......无论如何,我会继续调查。谢谢!
  • @cerealex 如果*ngIf*ngFor 在同一个DOM 元素上,这是一个已知问题 - 有人可能希望他们以多种方式进行交互,最后我检查了 Angular 开发人员倾向于只是说“不要这样做”,而不是试图选择一个。 *ngIf 会在其数据发生变化时动态更新,但不要将其放在与 *ngFor 相同的 DOM 节点上。
  • 是的,我了解到这一点,因为它不断返回错误。虽然它不起作用的原因是因为我使用的是let deleted 而不是this.deleted。尽管ngIf 现在确实做出了反应,但它会从 dom 中删除所有项目,而应该只删除一个项目。这就是现在的视图:<li *ngFor="let noticia of noticias"><div *ngIf="deleted===noticia.id">content</div></li>
【解决方案2】:

其实你的删除功能应该是这样的。

deleteNoticia(id){
    this._apiNoticias.deleteNoticia(id)
      .catch((err) => {
      console.log(err);
      });
    this.cd.markForCheck();
    this.ngOnInit();
  }

您需要再次调用 ngOnInit() 函数才能再次获取列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 2016-05-15
    相关资源
    最近更新 更多