Angular 6路由切换时侧边栏未自动更新问题求助
Hey there, let's break down why your named router-outlet isn't updating automatically when you switch routes—this is a super common pitfall with Angular's named outlets, and I’ve helped a bunch of devs fix this exact issue.
The Core Problem
Your setup has two key issues preventing the named side-bar outlet from updating:
- You're relying on empty-path routes for your named outlets, and Angular doesn't trigger a component refresh when the parent route changes but the child outlet route stays empty.
- You're not explicitly targeting the
side-baroutlet when navigating between routes—Angular can't guess which outlet you want to update unless you tell it.
Step 1: Fix Your Route Configuration
First, let's adjust your routing to avoid ambiguous empty-path matches for named outlets. We'll add explicit sub-paths for the sidebar routes (or keep empty paths but ensure navigation targets them properly):
// app-routing.module.ts const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'home', redirectTo: "", pathMatch: "full" }, { path: '', canActivate: [AuthGuard], component: LayoutComponent, children: [ { path: '', component: HomeComponent, pathMatch: "full", outlet:"main600" }, { path: '', component: HomesidebarComponent, outlet:"side-bar", pathMatch: "full" }, { path: 'community/:communityName', canActivateChild: [CommunityGuard], children: [ { path: '', component: CommunityComponent }, { path: 'about', component: CommunityaboutComponent }, { path: 'channels', component: ChannelsComponent, data: {roles:['member','owner','moderator']} }, { path: 'channel/:channelId', children: [ // Main content outlet { path: '', component: ChannelComponent, outlet:"main600", pathMatch: "full", data: {roles:['member','owner','moderator']} }, // Explicit sidebar route (can use empty path, but navigation must target it) { path: 'sidebar', component: ChannelsidebarComponent, outlet:"side-bar", data: {roles:['member','owner','moderator']} }, { path: 'createarticle', component: CreatearticleComponent, data: {roles:['member','owner','moderator']} }, { path: 'createpoll', component: CreatepollComponent, data: {roles:['member','owner','moderator']} }, { path: 'post/:postId', children:[ { path:'', component: PostComponent, outlet:"main600", pathMatch: "full", data: {roles:['member','owner','moderator']} }, { path:'sidebar', component: ChannelsidebarComponent, outlet:"side-bar", data: {roles:['member','owner','moderator']} }, ] } ] } ] } ] } ];
Step 2: Explicitly Target the Named Outlet When Navigating
This is the most critical fix. Whenever you navigate to a route that should update the side-bar outlet, you need to specify it in your routerLink or programmatic navigation.
Template (routerLink) Example:
If you're navigating from a community page to a channel:
<a [routerLink]="['community', communityName, 'channel', channelId, { outlets: { 'side-bar': ['sidebar'] } }]" > View Channel </a>
If you're navigating from a channel to a post:
<a [routerLink]="['post', postId, { outlets: { 'side-bar': ['sidebar'] } }]" relativeTo="activatedRoute" > View Post </a>
Programmatic Navigation Example:
If you're using router.navigate in a component:
import { Router, ActivatedRoute } from '@angular/router'; constructor(private router: Router, private activatedRoute: ActivatedRoute) {} navigateToPost(postId: string) { this.router.navigate([ '.', 'post', postId, { outlets: { 'side-bar': ['sidebar'] } } ], { relativeTo: this.activatedRoute }); }
Step 3: (Optional) Clean Up the Template's Display Logic
Your current template uses location.path() to show/hide outlets, which can lead to race conditions with route changes. Instead, use Angular's Router service to subscribe to route events or check route data:
// LayoutComponent.ts import { Router, ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; showSidebar$: Observable<boolean>; constructor(private router: Router, private activatedRoute: ActivatedRoute) { this.showSidebar$ = this.router.events.pipe( map(() => { const path = this.router.url; return path === '' || (path.includes('/channel/') && !path.includes('createpoll') && !path.includes('createarticle')); }) ); }
Then update your template to use the observable:
<div fxFlex="300px" fxHide.lt-md="true" *ngIf="showSidebar$ | async" style="margin-top:4em" > <router-outlet name="side-bar"></router-outlet> </div>
Why This Works
By explicitly targeting the side-bar outlet in your navigation, you're telling Angular to destroy the old sidebar component and render the new one whenever the route changes. Without this, Angular assumes the empty-path route for the outlet is still valid and doesn't trigger a refresh.
内容的提问来源于stack exchange,提问作者aryana

