我最近从5号角升级到7号角。从最近的ng-conf看了Deborah Kurata的this演讲后,我决定更新我相当糟糕的路由代码。
我决定在应用程序组件之上实现她关于shell组件的想法,以处理路由,然后在需要时延迟加载每个功能模块。这是我到目前为止的内容:
app.component.html
<router-outlet></router-outlet>
app-routing.module.ts
import { Injectable, NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AccessGuard } from './shared/guards/access.guard';
import { LoginComponent } from './login/login.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
export const appRoutes: Routes = [
{
path: 'login',
component: LoginComponent,
data: { requiresLogin: false },
canActivate: [ AccessGuard ]
},
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [ RouterModule.forRoot(appRoutes) ],
exports: [ RouterModule ],
providers: [ AccessGuard ]
})
export class AppRoutingModule {}
因此,在这里您可以看到我只关心应用程序根目录中的登录和页面未找到视图。下面是应作为其他所有设备的主要路由器的shell.module:
shell.component.html
<app-header></app-header>
<router-outlet name="primary"></router-outlet>
shell-routing.module.ts
import { Injectable, NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Observable } from 'rxjs';
import { AccessGuard } from '../shared/guards/access.guard';
import { DashboardComponent } from '../dashboard/dashboard.component';
import { ShellComponent } from './shell.component';
export const shellRoutes: Routes = [
{
path: '',
component: ShellComponent,
data: { requiresLogin: true },
canActivate: [ AccessGuard ],
children: [
{
path: 'dashboard',
component: DashboardComponent,
data: { requiresLogin: true },
canActivate: [ AccessGuard ]
},
{
path: 'posts',
loadChildren: 'app/posts/posts.module#PostsModule'
},
{
path: 'user-profile',
loadChildren: 'app/user-profile/user-profile.module#UserProfileModule'
}
]
},
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
}
];
@NgModule({
imports: [ RouterModule.forChild(shellRoutes) ],
exports: [ RouterModule ],
providers: [ AccessGuard ]
})
export class ShellRoutingModule {}
同样,如您所见,我懒于加载Posts和UserProfile模块。最后是上述模块路线:
posts-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccessGuard } from '../shared/guards/access.guard';
import { PostsComponent } from './posts.component';
import { PostComponent } from './post/post.component';
const postsRoutes: Routes = [
{
path: '',
redirectTo: 'add',
pathMatch: 'full'
},
{
path: 'add',
component: PostComponent,
data: { requiresLogin: true },
canActivate: [ AccessGuard ],
},
{
path: 'comment/:id',
component: PostComponent,
data: { requiresLogin: true },
canActivate: [ AccessGuard ],
},
{
path: 'edit/:id',
component: PostComponent,
data: { requiresLogin: true },
canActivate: [ AccessGuard ],
}
];
@NgModule({
imports: [ RouterModule.forChild(postsRoutes) ],
exports: [ RouterModule ],
providers: [ AccessGuard ]
})
export class PostsRoutingModule { }
user-profile-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccessGuard } from '../shared/guards/access.guard';
import { UserProfileComponent } from './user-profile.component';
import { FollowersComponent } from './followers/followers.component';
import { FollowingComponent } from './following/following.component';
import { MentorsComponent } from './mentors/mentors.component';
import { CoachesComponent } from './coaches/coaches.component';
import { NotificationsComponent } from './notifications/notifications.component';
import { AdminMentorComponent } from './admin-mentor/admin-mentor.component';
const userProfileRoutes: Routes = [
{
path: 'user-profile',
data: { requiresLogin: true },
children: [
{
path: ':id',
data: { requiresLogin: true },
canActivate: [ AccessGuard ],
children: [
{
path: '',
component: UserProfileComponent,
},
{
path: 'followers',
component: FollowersComponent
},
{
path: 'following',
component: FollowingComponent
},
{
path: 'mentors',
component: MentorsComponent
},
{
path: 'coaches',
component: CoachesComponent
},
{
path: 'notifications',
component: NotificationsComponent
}
]
}
]
}
];
@NgModule({
imports: [ RouterModule.forChild(userProfileRoutes) ],
exports: [ RouterModule ],
providers: [ AccessGuard ]
})
export class UserProfileRoutingModule { }
问题
基于以上所述,为什么标题出现在帖子路线上,而没有出现在用户个人资料路线上?
编辑
不幸的是,我无法在StackBlitz上模拟行为。一切都会出现。我将把header.component代码注释掉,然后用其他代码替换它,看看它是否出现。
编辑2
如我先前的编辑中所述,我可以正确模拟行为。我可以想到的另一个演示问题的方法是:当我导航到posts
路线时,如下所示:
<input placeholder="How are you today?" routerLink="/posts/add">
我在DOM树中看到正确的路由器出口(shell.component中的一个)是目标,并且post组件(app-post)位于其旁边:
但是,用户配置文件的组件无法执行此操作。他们改为进入app.component旁边,而不是shell.component中的那个。我将路由硬编码为用户个人资料,如下所示:
<p routerLink="/user-profile/6">Testing testing</p>
进行测试,但标题结果消失了。
对我来说,这真是奇怪的行为。这两个组件路由都被导入到shell-routing.module中,因此应该将它们的组件放在其旁边。
那有什么呢?
还-我的意思是,当您尝试通过“ / some-path / here”导航时,您使用的是绝对路径,而不是相对路径,因此它应该可以工作?嘟嘟嘟
答案 0 :(得分:0)
发生这种情况的原因是,当您在Angular中延迟加载模块并将路由定义为子级时,其父级必须包含package sample;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.sql.*;
import java.util.ArrayList;
import java.util.TimeZone;
//Author: Yerbol
//SQL database "sqlbase_schema" contains a Table "sqlbase_table" with 3 columns: "id" (Integer(INT(11))), "name" (String(VARCHAR(45))), "married" (Boolean(TINYINT(1)));
public class Main extends Application {
private TableView<Person> tableView = new TableView<>();
@Override
public void start(Stage primaryStage) throws SQLException, ClassNotFoundException {
//Show window
buildData();
Parent root = tableView;
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public void buildData() throws ClassNotFoundException, SQLException {
Connection dbConnection;
//SQL Database connection params
String dbHost = "localhost";
String dbPort = "3306";
String dbUser = "root";
String dbPassword = "12345";
String dbName = "sqlbase_schema";
String dbTableName = "sqlbase_table";
String select = "SELECT * FROM " + dbTableName;
String connectionString = "jdbc:mysql://" + dbHost + ":" + dbPort +"/" + dbName+"?useLegacyDatetimeCode=false&&serverTimezone=" + TimeZone.getDefault().getID();
Class.forName("com.mysql.cj.jdbc.Driver");
//Connecting to Database
dbConnection = DriverManager.getConnection(connectionString, dbUser, dbPassword);
//Extracting data from Databasee
ResultSet resultSet = null;
try {
PreparedStatement preparedStatement = dbConnection.prepareStatement(select);
resultSet = preparedStatement.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
ObservableList dbData = FXCollections.observableArrayList(dataBaseArrayList(resultSet));
//Giving readable names to columns
for(int i=0 ; i<resultSet.getMetaData().getColumnCount(); i++) {
TableColumn column = new TableColumn<>();
switch (resultSet.getMetaData().getColumnName(i+1)) {
case "id":
column.setText("ID #");
break;
case "name":
column.setText("Person Name");
break;
case "married":
column.setText("Marital Status");
break;
default: column.setText(resultSet.getMetaData().getColumnName(i+1)); //if column name in SQL Database is not found, then TableView column receive SQL Database current column name (not readable)
break;
}
column.setCellValueFactory(new PropertyValueFactory<>(resultSet.getMetaData().getColumnName(i+1))); //Setting cell property value to correct variable from Person class.
tableView.getColumns().add(column);
}
//Filling up tableView with data
tableView.setItems(dbData);
}
public class Person {
IntegerProperty id = new SimpleIntegerProperty(); //variable names should be exactly as column names in SQL Database Table. In case if you want to use <int> type instead of <IntegerProperty>, then you need to use getter/setter procedures instead of xxxProperty() below
StringProperty name = new SimpleStringProperty();
BooleanProperty married = new SimpleBooleanProperty();
public IntegerProperty idProperty() { //name should be exactly like this [IntegerProperty variable name (id) + (Property) = idProperty] (case sensitive)
return id;
}
public StringProperty nameProperty() {
return name;
}
public BooleanProperty marriedProperty() {
return married;
}
public Person(int idValue, String nameValue, boolean marriedValue) {
id.set(idValue);
name.set(nameValue);
married.set(marriedValue);
}
Person(){}
}
//extracting data from ResulSet to ArrayList
private ArrayList dataBaseArrayList(ResultSet resultSet) throws SQLException {
ArrayList<Person> data = new ArrayList<>();
while (resultSet.next()) {
Person person = new Person();
person.id.set(resultSet.getInt("id"));
person.name.set(resultSet.getString("name"));
person.married.set(resultSet.getBoolean("married"));
data.add(person);
}
return data;
}
public static void main(String[] args) {
launch(args);
}
}
才能添加该子级,否则它将无法正常工作。
另一个关键点是进行更改时,例如除了添加延迟加载的模块或对其路由进行修改之外,您需要重新启动应用并使用router-outlet
标志为其提供服务:
--aot
看到您的更改生效。