【问题标题】:Nativescript Angular Routing from 1 Child module to another in a Tabs setup选项卡设置中从 1 个子模块到另一个子模块的 Nativescript Angular 路由
【发布时间】:2019-11-29 05:22:53
【问题描述】:

我在我的 Nativescript Angular 项目中为选项卡使用 <page-router-outlet></page-router-outlet><BottomNavigation></BottomNavigation> 设置,并且在从 1 个子选项卡路由导航到另一个子选项卡路由时遇到问题。

所以这里是app-routing.module.ts

const routes: Routes = [
    { path: '', redirectTo: '/auth', pathMatch: 'full' },
    { path: 'auth', component: AuthComponent },
    { path: 'individual-tasks', component: SpecificTasksComponent },
    {
        path: 'tabs',
        component: TabsComponent,
        children: [
            {
                path: 'feed',
                loadChildren: '~/app/pages/feed/feed.module#FeedModule',
                component: NSEmptyOutletComponent,
                outlet: 'feedTab'
            },
            {
                path: 'notification',
                loadChildren: '~/app/pages/notification/notification.module#NotificationModule',
                component: NSEmptyOutletComponent,
                outlet: 'notificationTab'
            },
            {
                path: 'create',
                loadChildren: '~/app/pages/create/create.module#CreateModule',
                component: NSEmptyOutletComponent,
                outlet: 'createTab'
            },
            {
                path: 'profile',
                loadChildren: '~/app/pages/profile/profile.module#ProfileModule',
                component: NSEmptyOutletComponent,
                outlet: 'profileTab'
            }
        ]
    }
];

我目前正在尝试从创建选项卡模块导航到提要选项卡模块。这里是create-routing.module.ts

const routes: Routes = [
    { path: '', redirectTo: 'create', pathMatch: 'full' },
    { path: 'create', component: CreateComponent },
    { path: 'create-tasks', component: CreateTasksComponent },
    { path: 'create-preview', component: CreatePreviewComponent }
];

那么,如果我目前在 create-preview 路线内,我该如何导航回 app-routing.module.ts 中的“标签/提要”出口?

我一直在尝试这个:

        this.router.navigate([
            '../tabs', {
                outlets: { feedTab: ['feed'] }, relativeTo: this.activatedRoute
            }
        ]);

但即使我明确写到导航应该是到 feedTab,它仍然导航到起始出口(配置文件)而不是 feed 出口。这就像所说的出口完全被忽略了......有什么想法吗???

【问题讨论】:

  • 我不认为路由器让你能够切换标签。您必须更新标签的 selectedIndex,然后导航到您喜欢的特定标签。
  • 我认为@Manoj 是正确的......现在我必须弄清楚如何从其子组件之一中更新 selectedIndex
  • 使用带有行为主题的服务。从父组件监听主题,更新子组件的值。

标签: angular nativescript angular-routing angular2-nativescript nativescript-angular


【解决方案1】:

其中一位 cmets 要求澄清如何为此目的使用 BehaviorSubject,因此我将发布此代码以防将来对某人有所帮助。这将展示如何使用 rxjs BehaviorSubject 来监听选项卡的变化,并提供一种在使用此服务的应用程序内的任何位置更改 BottomNavigation 的当前选项卡的方法。

此服务的目的是提供一个可以在整个应用程序中访问 BottomNavigation UI 元素的中心位置。它可以:

  • 使用ElementRefBottomNavigation,以便可以访问nativeElement 以获取或更改BottomNavigation 元素的当前选项卡。
  • 提供一个 rxjs BehaviorSubject observable,允许此服务的消费者订阅并通知 BottomNavigation selectedIndexChanged 事件。 newIndexoldIndex 是从这个 rxjs BehaviorSubject 在每个 BottomNavigation selectedIndexChanged 事件上可观察到的。

注意:在其模板中包含 BottomNavigation 元素的组件中(本例中为 app.component.ts),它必须提供此 NavigationService在其ngAfterViewInit 生命周期挂钩中需要对BottomNavigation 的引用,例如:this._navigationService.bottomNavigationRef = this.navRef; (请参阅下面 app.component.ts 中的 sn-p)

// navigation.service.ts

import { ElementRef, Injectable, OnDestroy } from '@angular/core';

import { BottomNavigation, SelectedIndexChangedEventData } from '@nativescript/core';

import { BehaviorSubject, Subscription } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class NavigationService implements OnDestroy {
  private _bottomNavigationRef: ElementRef<BottomNavigation>;
  private _subscription: Subscription;
  private callbackSelIndexChgEv;
  /** rxjs BehaviorSubject observable to track the current tab of the BottomNavigation */
  bottomNavigationTab$: BehaviorSubject<{ newIndex: number; oldIndex: number }>;

  constructor() {
    // Must initialize rxjs BehaviorSubject observable with initial value.
    this.bottomNavigationTab$ = new BehaviorSubject({
      newIndex: -1,
      oldIndex: -1,
    });

    // Logs the current tab per this service.
    this._subscription = this.bottomNavigationTab$.subscribe((value) => {
      console.log(
        `NavigationService -> The BottomNavigation current tab index is now:
            newIndex: "${value.newIndex}"
            oldIndex: "${value.oldIndex}"`
      );
    });
  }

  ngOnDestroy(): void {
    this._subscription.unsubscribe();
    this._bottomNavigationRef.nativeElement.off(
      BottomNavigation.selectedIndexChangedEvent,
      this.callbackSelIndexChgEv
    );
  }

  get bottomNavigationRef(): ElementRef<BottomNavigation> {
    return this._bottomNavigationRef;
  }

  set bottomNavigationRef(bottomNavRef: ElementRef<BottomNavigation>) {
    this._bottomNavigationRef = bottomNavRef;

    this.callbackSelIndexChgEv = (
      $event: SelectedIndexChangedEventData
    ): void => {
      /* Update the current tab of the rxjs BehaviorSubject Observable */
      this.bottomNavigationTab$.next({
        newIndex: $event.newIndex,
        oldIndex: $event.oldIndex,
      });
    };

    this._bottomNavigationRef.nativeElement.on(
      BottomNavigation.selectedIndexChangedEvent,
      this.callbackSelIndexChgEv
    );
  }
}

// app.component.ts (partial file)

// ...
 @ViewChild('bottomNav') navRef: ElementRef<BottomNavigation>;
// ...
ngAfterViewInit(): void {
    // Gives the NavigationService the reference to the BottomNavigation it needs.
    this._navigationService.bottomNavigationRef = this.navRef;
}
// ...
<!-- app.component.html (partial file just to show #bottomNav) -->
<BottomNavigation #bottomNav>
<!-- ... -->
</BottomNavigation>
// another.component.ts

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

import { Subscription } from 'rxjs';

import { NavigationService } from './navigation.service';

@Component({
  selector: 'app-another-component',
  templateUrl: './another.component.html',
  styleUrls: ['./another.component.scss']
})
export class AnotherComponent implements OnDestroy, OnInit {
  private _subscription: Subscription;

  constructor(private _navigationService: NavigationService) {}

  ngOnInit(): void {
    // Example using BehaviorSubject Observable:
    this._subscription = this._navigationService.bottomNavigationTab$.subscribe(
      (selectedTab) => {
        console.log(`This component knows that the BottomNavigation current tab is now: ${selectedTab.newIndex} and the old tab was: ${selectedTab.oldIndex}`);

        if (selectedTab.newIndex === 2) {
          // do something ...
        }
      }
    );
  }

  ngOnDestroy(): void {
    // unsubscribe from BehaviorSubject Observable
    this._subscription.unsubscribe();
  }

  // Example changing the BottomNavigation tab from another component:
  changeTab(tab: number): void {
    this._navigationService.bottomNavigationRef.nativeElement.selectedIndex = tab;
  }

}

rxjs BehaviorSubject 文档:https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject

【讨论】:

  • 效果很好。谢谢
【解决方案2】:

我认为路由器无法让您切换标签。您必须更新BottomNavigationselectedIndex,然后导航到您喜欢的特定标签。

要从子组件更新selectedIndex,请使用带有BehaviorSubject 的服务。从父组件监听主题,从子组件更新值。

【讨论】:

  • 感谢@Manoj 的帮助,我能够使用 BehaviorSubject 模型导航到不同的索引......但是,在导航之后,我导航的那个选项卡中的所有内容都消失了。所以它只是在导航后显示一个空白的白页,但如果我导航到另一个选项卡然后返回,所有组件都会返回并再次可见。这敲响了警钟吗?
  • @WJosh Vetter 你好 Manoj,Josh 你能解释一下 BehaviorSubject 的解决方案是如何工作的吗?
  • @LimyandiVicoTrico 我发布了一个答案,展示了 BehaviorSubject 如何与示例代码一起使用。
【解决方案3】:

试试这个:

您需要从navigate()中删除this.activatedRoute,这是在您现在提供的路由路径之前分配当前路由。

 this.router.navigate(['../tabs/feed', {
       outlets: {  primary: ['feed'], feedTab: ['feed'] }
    }
 ])

您可以阅读有关outlets here 的更多信息并关注此博客以了解更多details

希望这会有所帮助.. :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 2016-08-28
    • 2018-03-14
    相关资源
    最近更新 更多