NS6.1+Angular8:为BottomNavigation动态添加带PageRouterOutlet的TabContentItem
嘿,我刚好在NativeScript Angular 8的项目里处理过类似的场景,给你两个实用方案,帮你搞定动态TabContentItem绑定PageRouterOutlet的问题!
方案一:完全动态创建(用ComponentFactoryResolver)
如果需要完全通过代码生成所有标签页和路由出口,可以借助Angular的ComponentFactoryResolver来动态实例化PageRouterOutlet,并绑定到TabContentItem中。
步骤1:组件类实现
在你的主组件(比如MainComponent)中注入必要的依赖,然后编写动态创建标签页的逻辑:
import { Component, ComponentFactoryResolver, ViewContainerRef, OnInit } from "@angular/core"; import { TabContentItem, TabStripItem } from "tns-core-modules/ui/bottom-navigation"; import { PageRouterOutlet } from "nativescript-angular/router"; @Component({ selector: "app-main", templateUrl: "./main.component.html" }) export class MainComponent implements OnInit { contentItems: TabContentItem[] = []; stripItems: TabStripItem[] = []; constructor( private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef ) {} ngOnInit() { // 按需创建标签页,这里示例创建两个 this.addTab("首页", "home-outlet", "home"); this.addTab("我的", "profile-outlet", "profile"); } private addTab(title: string, outletName: string, routePath: string) { // 1. 创建TabStripItem并添加到数组 const tabStripItem = new TabStripItem(); tabStripItem.title = title; this.stripItems.push(tabStripItem); // 2. 创建TabContentItem const tabContentItem = new TabContentItem(); // 3. 动态创建PageRouterOutlet组件 const outletFactory = this.componentFactoryResolver.resolveComponentFactory(PageRouterOutlet); const outletComponentRef = this.viewContainerRef.createComponent(outletFactory); // 设置路由出口的唯一名称(必须和路由配置对应) outletComponentRef.instance.name = outletName; // 将路由出口绑定到TabContentItem的content tabContentItem.content = outletComponentRef.location.nativeElement; this.contentItems.push(tabContentItem); } }
步骤2:配置路由
确保你的路由配置中包含对应每个出口的子路由,并且初始重定向要覆盖所有路由出口:
// app-routing.module.ts import { NgModule } from "@angular/core"; import { Routes } from "@angular/router"; import { NativeScriptRouterModule } from "nativescript-angular/router"; import { MainComponent } from "./main/main.component"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; const routes: Routes = [ { path: "", component: MainComponent, children: [ // 初始重定向到所有路由出口的组合路径 { path: "", redirectTo: "(home-outlet:home//profile-outlet:profile)", pathMatch: "full" }, // 每个路由对应一个出口 { path: "home", component: HomeComponent, outlet: "home-outlet" }, { path: "profile", component: ProfileComponent, outlet: "profile-outlet" } ] } ]; @NgModule({ imports: [NativeScriptRouterModule.forRoot(routes)], exports: [NativeScriptRouterModule] }) export class AppRoutingModule { }
步骤3:注册Entry Component(Angular 8及以下需要)
因为我们是动态创建PageRouterOutlet,需要在根模块中把它声明为entryComponents:
// app.module.ts import { NgModule } from "@angular/core"; import { PageRouterOutlet } from "nativescript-angular/router"; @NgModule({ ... entryComponents: [PageRouterOutlet] }) export class AppModule { }
方案二:模板驱动动态生成(更简洁)
如果不需要完全通过代码生成,只是需要根据数据动态渲染标签页,可以用*ngFor在模板中直接循环生成TabContentItem和PageRouterOutlet,这种方式更直观。
模板代码
<!-- main.component.html --> <BottomNavigation> <TabStrip> <TabStripItem *ngFor="let tab of tabConfig"> <Label [text]="tab.title"></Label> </TabStripItem> </TabStrip> <TabContentItem *ngFor="let tab of tabConfig"> <PageRouterOutlet [name]="tab.outletName"></PageRouterOutlet> </TabContentItem> </BottomNavigation>
组件类代码
import { Component, OnInit } from "@angular/core"; // 定义标签页配置接口 interface TabConfig { title: string; outletName: string; routePath: string; } @Component({ selector: "app-main", templateUrl: "./main.component.html" }) export class MainComponent implements OnInit { tabConfig: TabConfig[] = []; ngOnInit() { // 初始化标签页配置 this.tabConfig = [ { title: "首页", outletName: "home-outlet", routePath: "home" }, { title: "我的", outletName: "profile-outlet", routePath: "profile" } ]; } }
路由配置和方案一完全一致,这里就不再重复了。
关键注意事项
- 每个
PageRouterOutlet必须有唯一的name属性,并且和路由配置中的outlet字段严格匹配,否则路由无法正确加载。 - 初始重定向路径必须采用
(outlet1:path1//outlet2:path2)的格式,确保所有标签页的初始路由都能被加载。 - 确保已经正确导入
NativeScriptRouterModule,并且所有页面组件都已在模块中声明或导入。
内容的提问来源于stack exchange,提问作者Tihomir Mihaylov
相关产品推荐
相关产品推荐

