角度组件 - 如何避免嵌套组件

Posted

技术标签:

【中文标题】角度组件 - 如何避免嵌套组件【英文标题】:angular component - how to avoid having nested components 【发布时间】:2018-11-25 00:14:10 【问题描述】:

您好,我正在学习 Angular,我对组件有疑问。我有两个组件,一个是根,一个是另一个。当我从 root 转到另一个时,我会看到来自 root 控制器的内容。看起来 Angular 创建了子组件,它使子组件保持来自父级的内容。但是我怎样才能显示一个全新的模板呢?这是我拥有的两个控制器。我还可以验证从 html 页面创建的第二个组件是在根组件的部分下创建的。

这是根控制器。

ma​​rket-data.component.ts

import  Component, OnInit, Inject  from "@angular/core";
import  MarketDataService  from "./market-data.service";
import  CoinMarketCapTokenEntity  from "../entity/coinmarketcaptoken-entity";

@Component(
    selector: "app-market-data",
    templateUrl: "./src/app/market-data.component.html"
)
export class MarketDataComponent implements OnInit 
    private _marketDataService: MarketDataService;
    private tokens: any;

    constructor(marketDataService: MarketDataService) 
        this._marketDataService = marketDataService;
    

    ngOnInit() 
        /*this._marketDataService.getCoinMarketCapTokens()
            .subscribe(res => this.tokens = res);*/
        this.tokens = [
            
                symbol: "BTC"
            ,
            
                symbol: "ETH"
            
        ];
    

ma​​rket-data.component.html

<table class="table table-sm table-hover">
    <thead>
        <tr>
            <th scope="col">Symbol</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let token of tokens">
            <td>
                <a [routerLink]="['/marketData', token.symbol]">
                     token.symbol 
                </a>
            </td>
        </tr>
    </tbody>
</table>
<router-outlet></router-outlet>

这是第二个(子)组件

kline.component.ts

import  Component, Input, OnInit, OnDestroy  from "@angular/core";
import  ActivatedRoute, Router  from "@angular/router";
import  MarketDataService  from "./market-data.service";

@Component(
    selector: "app-kline",
    template: `
        <section *ngIf="currentSymbol">
            <h2>You selected:  currentSymbol </h2>
        </section>

        <!-- New Button Here -->
        <button (click)="goToMarketDataList()">Back to Market Data List</button>
    `
)
export class KLineComponent implements OnInit, OnDestroy 
    private marketDataService: MarketDataService;
    private route: ActivatedRoute;
    private router: Router;
    private sub: any;

    // bind symbol here
    @Input() currentSymbol: string;

    constructor(marketDataService: MarketDataService,
                route: ActivatedRoute,
                router: Router) 
        this.marketDataService = marketDataService;
        this.route = route;
        this.router = router;
    

    ngOnInit() 
        this.sub = this.route.params.subscribe(params => 
            let symbol = params["market"];
            //this.currentSymbol = this.marketDataService.getToken(symbol).symbol;
            this.currentSymbol = "BTC";
        );
    

    ngOnDestroy(): void 
        this.sub.unsubscribe();
    

    goToMarketDataList() 
        let link = ["/"];
        this.router.navigate(link);
    

app.module.ts

import  NgModule  from "@angular/core";
import  BrowserModule  from "@angular/platform-browser";
import  FormsModule  from "@angular/forms";
import  HttpClientModule  from "@angular/common/http";

import  MarketDataComponent  from "./app/market-data.component";
import  MarketDataService  from "./app/market-data.service";
import  KLineComponent  from "./app/kline.component";

import  appRouterModule  from "./app.routes";

@NgModule(
    imports: [
        BrowserModule,
        FormsModule,
        HttpClientModule,
        appRouterModule
    ],
    declarations: [
        MarketDataComponent,
        KLineComponent
    ],
    bootstrap: [
        MarketDataComponent
    ],
    providers: [
        MarketDataService
    ]
)
export class AppModule 

如果有帮助,还可以配置路由。

app.routes.ts

import  Routes, RouterModule  from "@angular/router";
import  MarketDataComponent  from "./app/market-data.component";
import  KLineComponent  from "./app/kline.component";

const routes: Routes = [
    
        path: "marketData/:market",
        component: KLineComponent
    
];

export const appRouterModule = RouterModule.forRoot(routes);

【问题讨论】:

请在 stackbiz 提供代码, 我没有你的组件模板,但我假设你在你的父级中写了一个&lt;app-kline&gt; 选择器,因为你有一个@Input。我建议您重新阅读有关组件交互的官方文档,以及何时应该使用父子组件而不是路由组件。 @tricheriche 很遗憾,我忘记分享了。我加了。 @PranayRana 是的,当然。我以前从未使用过stackbiz。一旦我从该站点提供代码,我将编辑帖子 既然您的父模板中没有&lt;app-kline&gt;,为什么您的子组件中有@Input?你如何使用它? 【参考方案1】:

这是因为您的根组件中有&lt;router-outlet&gt;。所有通过路由渲染的组件都将加载到&lt;router-outlet&gt;中。

你应该做的是,在根组件的模板中只放&lt;router-outlet&gt;&lt;/router-outlet&gt;,比如AppComponent,并为MarketDataComponent创建一个不同的组件,并为其添加一个路由。

您可以添加一个默认路由,例如:


    path: "",
    component: MarketDataComponent
,

    path: "marketData/:market",
    component: KLineComponent

所以,默认情况下,当没有路由而只有“/”时,MarketDataComponent会先加载到AppComponent的router-outlet中,导航到KLineComponent后会再次加载到AppComponent的router-outlet中替换 MArketDataComponent。

【讨论】:

谢谢!这行得通。我正在阅读来自blog.angular-university.io/angular2-router 的关于路由器的博客文章。几乎发现它与路由器有关。 @quartaela 没问题。我建议你去看看官方文档。真的很棒。 angular.io/docs

以上是关于角度组件 - 如何避免嵌套组件的主要内容,如果未能解决你的问题,请参考以下文章

如何避免嵌套订阅超过两个级别

有没有办法在角度上实现两步路由?

如何扩展默认角度原理图“ng生成组件”

嵌套组件如何在角度 5 或 6 中工作

嵌套组件页面渲染完了还请求不到数据

如何以角度动态创建 n 级嵌套展开/折叠组件