【问题标题】:Angular view not updating, calling method from one component to another角度视图未更新,从一个组件调用方法到另一个组件
【发布时间】:2021-01-10 08:10:51
【问题描述】:

我正在尝试从另一个组件调用一个组件,我正在调用该组件的一个方法,该方法被调用没有任何问题,但是该组件的视图没有刷新,下面是一个演示代码来展示我的内容我正在努力。

myFirstComponent.component.ts

ngOnInit() {
        this.secondComponent = new SecondComponent();
        this.secondComponent.showValues(5)
}

second-component.component.ts

ngOnInit() {
       this.value = 10;    
       this.showValues(this.value)     
}

showValues(value: any) {
        this.newValue = value;
        console.log('This is console value' + this.newValue)
} 

在我的 HTML 中,

New Value is {{newValue}}

第一次加载组件时的输出将是

New Value is 10
 //in console it will be This is console value 10

从第一个组件调用 showValues 时的输出

New Value is 10
// in console it will be, This is console value 5

所以变量值得到了更新,但它没有反映在 UI 上,我的第二个组件永远不会刷新,这甚至是一个很好的做法,还是有其他方法可以实现这一点? 谢谢。

【问题讨论】:

  • 您不应该从一种方法调用第二个组件。你应该依靠 Angular 来为你做这件事。如果你能解释这两个组件之间的关系,那么我想我们可以用更多 Angular 的方式来完成它。
  • @PrinceIsNinja 它们是兄弟组件,不是父组件或子组件
  • @Vikas,感谢您的建议,我会从您建议的链接中尝试

标签: angular typescript angular-components


【解决方案1】:

兄弟组件之间传递数据或调用方法

在组件之间传递数据时,我发现 RxJS `BehaviorSubject` 非常有用。

您也可以使用常规 RxJS Subject 通过服务共享数据,但这就是我更喜欢 BehaviorSubject 的原因。

  1. 它将始终返回订阅时的当前值 - 无需调用 onNext()。
  2. 它有一个 getValue() 函数来提取最后一个值作为原始数据。
  3. 它确保组件始终接收最新数据。
  4. 您可以使用asObservable() 从行为主题中获取可观察的信息 行为主体的方法。
  5. Refer this for more

示例

在服务中,我们将创建一个私有的 BehaviorSubject 来保存消息的当前值。我们定义了一个 currentMessage 变量来将这个数据流作为一个可观察的对象来处理,其他组件将使用它。最后,我们创建一个函数,在 BehaviorSubject 上调用 next 来改变它的值。

父组件、子组件和兄弟组件都接受相同的处理。我们在组件中注入 DataService,然后订阅 currentMessage observable 并将其值设置为等于 message 变量。

现在,如果我们在其中任何一个组件中创建一个函数来更改消息的值。更新后的值会自动广播到所有其他组件。

shared.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class SharedService {

  private eventSource = new BehaviorSubject<string>("default message");
  eventSubject = this.eventSource.asObservable();

  constructor() { }

  emitEvent(value: string) {
    this.eventSource.next(value)
  }

}

sibling.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";

@Component({
  selector: 'app-sibling1',
  template: `
     {{message}}
   `,
   styleUrls: ['./parent.component.css']
})
export class SiblingComponent1 implements OnInit {

  message: string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.eventSubject.subscribe(value =>  this.showValues(value));
  }
}

sibling.component.ts

import { Component, OnInit } from '@angular/core';
import { SharedService } from "../shared.service";

@Component({
  selector: 'app-sibling2',
  template: `
    {{message}}
    <button (click)="emitEvent()">New Message</button>
  `,
  styleUrls: ['./sibling2.component.css']
})
export class SiblingComponent2 implements OnInit {

  message: string;

  constructor(private service: SharedService) { }

// emit value in oninit
  ngOnInit() {
   this.service.emitEvent("Hello from Sibling-1");
  }

// emit value on event
  emitEvent() {
    this.service.emitEvent("Hello from Sibling");
  }   
}

为什么要使用服务?

Angular 将组件与服务区分开来,以增加模块化和可重用性。 and It's Good Practice to Delegate complex component logic to services

来自 Angular 样式指南
将组件中的逻辑限制为仅 视图所需的。所有其他逻辑应委托给 服务。

将可重用逻辑移至服务并保持组件简单和 专注于他们的预期目的。

为什么?逻辑可以被多个组件重用时放置在一个 服务并通过函数公开。

为什么?服务中的逻辑可以更容易地在单元测试中隔离, 而组件中的调用逻辑很容易被mock。

为什么?从 组件。

为什么?使组件保持苗条、修剪和集中。

在 Angular 中使用服务还可以确保您没有违反软件开发的 DRYSRP 原则,对于您的场景,最好的解决方案是使用服务

【讨论】:

  • 我应该做 this.eventSubject.next(value) 还是 this.eventSource.next(value) ??
  • 感谢您的解释,它运行良好...
  • @shreyshah 我更新了答案使用 this.eventSource.next(value)
猜你喜欢
  • 2018-07-07
  • 2018-10-18
  • 2017-08-19
  • 2019-02-24
  • 2020-04-05
  • 2018-10-01
  • 2018-06-15
  • 2018-09-20
相关资源
最近更新 更多