首页 新闻 会员 周边 捐助

angular: 园子博客后台遇到的处理 NavigationError 错误后的 sidebar 更新问题

0
悬赏园豆:30 [已解决问题] 解决于 2025-01-11 14:42

目前在改进中的博客后台在发生 NavigationError 路由错误时是这样处理的,在 NavigationStart 事件处理函数中先将当前 tab 设置为 active。由于遇到路由错误,RouteOutlet 没有加载当前 tab 对应的 component,RouteOutlet 中依然是前任 tab 的 component,其中包含 sidebar 子组件,所以 sidebar 中显示的依然是前任 tab 对应的内容,下面的 $sideBar.next(undefined!) 就是为了清除 sidebar 中的内容

async ngOnInit() {
    this._router.events.subscribe((ev) => {
        if (ev instanceof NavigationStart) {
            this.setActiveTab(ev.url);
            this.spinnerService.toggle(true);
        }
        else if (ev instanceof NavigationError) {
            this.notifyService.error('路由出错:' + ev.error);
            this.sideBarSvc.$sideBar.next(undefined!);
            this._changeDetector.markForCheck();
        }
}

更新 sidebar 是在 app-layout.component.ts 中完成的

ngOnInit() {      
    this._sideBarSvc.$sideBar.pipe(takeUntil(this._unSub)).subscribe(x => {
        this.sidebarVcr?.clear();
        if (x) this.sidebarVcr?.createEmbeddedView(x);
        this._changeDetectionRef.markForCheck();
    });
}

经验证,这个方法清除 sidebar 是可行的,但却带来一个后遗症。

比如当前所在 tab 是「文章」(对应的路径是/articles),点击「日记」tab(对应的路径是/diaries),由于路由配置问题造成下面的 NavigationError

NG04014: Invalid configuration of route 'diaries/': routes must have either a path or a matcher specified

这时「日记」tab 出于 active 状态,侧边栏内容被清空,博文列表区块显示的是 spinner,符合预期。

接着点击「文章」tab(出现 NavigationError 之前所在的 tab),问题来了,sidebar 没有更新,还是空白状态。

此时,只要点击其他 tab,比如「随笔」tab (对应的路径是/posts),sidebar 就能正常更新,然后再点击「文章」tab,sidebar 也正常了。

点击「文章」tab,RouteOutlet 中加载的是 ArticlesMainComponent,删减后的 template 文件内容如下:

<cnb-post-list [postType]="postType"></cnb-post-list>
@defer {
<cnb-article-sidebar></cnb-article-sidebar>
}

我们关心的是 sidebar,所以进一步看 <cnb-article-sidebar> 的 template 文件内容

<ng-template cnbLayoutSidebar>
    <cnb-sidebar header="博客后台" [items]="operations"></cnb-sidebar>
    <cnb-sidebar header="分类">
        <ng-template #sidebarContent>
            <cnb-sidebar-blog-categories></cnb-sidebar-blog-categories>
        </ng-template>
    </cnb-sidebar>
</ng-template>

关键就在上面的 cnbLayoutSidebar directive,是它触发 sidebar 的更新,下面是它的实现代码

@Directive({
    selector: '[cnbLayoutSidebar]',
})
export class LayoutSidebarDirective implements OnInit {
    constructor(
        private _sideBarSvc: SideBarService,
        private sideBar: TemplateRef<any>,
        private readonly categoryStore: BlogCategoryStore,
        @Inject(BLOG_CATEGORY_TYPE) private categoryType: BlogCategoryType) { }

    ngOnInit() {
        if (this.sideBar) {
            this.categoryStore.refresh(this.categoryType);
            this._sideBarSvc.$sideBar.next(this.sideBar);
        }
    }
}

不知道为什么这个地方在发生 NavigationError 后不能正常更新 sidebar

dudu的主页 dudu | 高人七级 | 园豆:28665
提问于:2025-01-10 21:41
< >
分享
最佳答案
0

解决了!问题的原因很简单,在发生 NavigationError 后再点击出错前所在的 tab,没有触发 ngOnInit 事件,所以没有触发 sidebar 更新。

只要在 NavigationEnd router event 发生时触发 sidebar 更新就解决了,改进后的代码如下:

@Directive({
    selector: '[cnbLayoutSidebar]',
})
export class LayoutSidebarDirective implements OnInit {

    constructor(
        router: Router,
        private _sideBarSvc: SideBarService,
        private sideBar: TemplateRef<any>,
        private readonly categoryStore: BlogCategoryStore,
        @Inject(BLOG_CATEGORY_TYPE) private categoryType: BlogCategoryType) {
        router.events
            .pipe(
                filter(ev => ev instanceof NavigationEnd),
                debounceTime(100),
                takeUntilDestroyed()
            )
            .subscribe((ev) => {
                this.updateSidebar();
            });
    }

    ngOnInit() {
        this.updateSidebar();
    }

    updateSidebar() {
        if (this.sideBar) {
            this.categoryStore.refresh(this.categoryType);
            this._sideBarSvc.$sideBar.next(this.sideBar);
        }
    }
}
dudu | 高人七级 |园豆:28665 | 2025-01-11 14:41
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册