将数组绑定到模板中的组件仅适用于页面加载



我的布局模板中有一个组件(用于导航栏(,我正在使用一个可注入的服务,因此组件可以根据自己的逻辑更改导航栏的内容。

以下是模板标记的一部分

默认布局.组件.html

<app-sidebar-nav [navItems]="defaultLayoutService.items$ | async" [perfectScrollbar] [disabled]="appSidebar.minimized"></app-sidebar-nav>

默认布局.组件.ts

constructor(public defaultLayoutService: DefaultLayoutService) {
}

默认布局服务.ts

import { navItems, ICustomNavData } from '../../_nav';
items$: Observable<ICustomNavData[]>;
navItems = <ICustomNavData[]>navItems; //cast to a custom interface I created.
setNavItemAttribute(itemKey: string, itemAttribute: string, text: string) {
let menuItem = this.navItems.find(r => r.key == itemKey);
if (menuItem && menuItem.hasOwnProperty(itemAttribute)) {
menuItem[itemAttribute] = text;
}
console.log(this.navItems); //this outputs the items and shows they were modified correctly
this.items$ = new Observable(ob => { ob.next(this.navItems); })
}

因此,我有一些组件也可以访问DefaultLayoutService,并使用不同的参数调用setNavItemAttribute

它工作,但只有当我刷新页面时。在单应用页面模式下浏览时,触发对具有不同参数的setNavItemAttribute的调用,导航项目保持不变。

我在这里正确处理Observable吗?

我在这里正确处理Observable吗?

我在这里看到了两个潜在的问题:

  1. 每次更新当前数组中的相应项时,都会将服务中的items$Observable设置为一个新实例
  2. 您将Observable的值设置为数组的同一实例,因此Angular的变化检测不会认为数组发生了变化(即使中的值发生了变化(

让我们来解决这些问题:

您可以使用中间Subject来触发从服务中在Observable上发出的值,并在需要更新值时对其调用.next

要做到这一点,可以将Observable作为从Subject构建的常规公开。这是为了防止外部影响能够无意/恶意地直接对受试者调用.next

看起来像这样:

export class DefaultLayoutService {
private _navItems: <ICustomNavData[]>;
private readonly _itemsSubject = new Subject<ICustomNavData[]>();
items$: Observable<ICustomNavData[]> = this._itemsSubject.asObservable();
setNavItemAttribute(itemKey: string, itemAttribute: string, text: string) {
// code to update corresponding item in navItems array

this._itemsSubject.next(this.navItems);
}
}

因为Observable来源于Subject,所以它将发出您在服务方法中传递给Subject的最新值。

请注意,在首次初始化组件和数组时,需要使用_itemsSubject的第一个值调用.next,以便在Observable上发出它。


在单应用页面模式下浏览时,触发对具有不同参数的setNavItemAttribute的调用,导航项保持不变。

因为对数组本身的引用没有更改,Angular的更改检测不会用数组内的新值重新渲染。这似乎是人们偶然发现的一个常见问题。

我以前做过的一种方法是使用CCD_;新的";数组,使用旧的。通过这种方式,引用是不同的,并触发更改检测以使用新值重新渲染。

像这样:

setNavItemAttribute(...) {
// code to update the corresponding item in the existing _navItems array
const navItemsCopy = [...this._navItems];
// use the new array reference to trigger change detection
this._itemsSubject.next(navItemsCopy);
}

有很多方法可以做到这一点,所以四处看看,看看什么最适合你的情况,什么感觉最适合你。

相关内容

  • 没有找到相关文章

最新更新