angular2 - 使用路由器问题

Posted

技术标签:

【中文标题】angular2 - 使用路由器问题【英文标题】:angular2 - issue by using router 【发布时间】:2017-08-12 17:11:52 【问题描述】:

首先,我是这种使用 nodejs、angular2 和 typescript 编程的初学者。基本上我开始阅读https://angular.io/docs/ts/latest/guide/forms.html 和https://angular.io/docs/ts/latest/guide/router.html#!#base-href 以用新页面扩展我的应用程序。我使用 mdl 在我的应用程序中使用材料组件。 angular 2 似乎手动重新加载和路由不同,所以我得到以下问题: 我试图了解发生了什么,有人可以解释一下 angular2 中重新加载和路由之间的区别以及我如何将路由处理适应重新加载的行为?

更新 #1: index.html:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Title</title>
  <script defer src="/assets/js/material.min.js"></script>
  <link rel="stylesheet" href="/assets/css/font-awesome.min.css">
  <link rel="stylesheet" href="/assets/css/material.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root><md-spinner></md-spinner></app-root>
</body>
</html>

app.module.ts

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';
import  FormsModule  from '@angular/forms';
import  HttpModule  from '@angular/http';
import  AppComponent  from './pages/layout/app.component';
import  HomeComponent  from './pages/home/app.component';
import  LoginComponent  from './pages/myaccount/login.component';
import  NotFoundComponent  from './pages/error/404.component';
import  RegisterComponent  from './pages/myaccount/register.component';
import  RouterModule, Routes  from '@angular/router';
import  LoginService  from './service/LoginService';

const appRoutes: Routes = [
  
      path: '',
      component: HomeComponent
  ,
   path: 'series', component: AppComponent ,
   path: 'login', component: LoginComponent ,
   path: 'register', component: RegisterComponent ,
   path: '**', component: NotFoundComponent 
];

@NgModule(
  declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent,
    RegisterComponent,
    NotFoundComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule.forRoot(appRoutes)
    ],
  providers: [LoginService],
  bootstrap: [AppComponent]
)
export class AppModule  

注册.html:

<div class="mdl-grid iv-padding" >
    <div class="mdl-layout-spacer"></div>
    <div class="mdl-cell mdl-cell--4-col">
      <div style="text-align:center;">
        <form (ngSubmit)="onSubmit()">
        <div class="iv-card-wide mdl-card mdl-shadow--2dp">
          <div class="mdl-card__title">
            <h2 class="mdl-card__title-text">Registrierung</h2>
          </div>
          <div class="mdl-card__supporting-text">
              <div class="text-field mdl-textfield mdl-js-textfield">
                <input class="mdl-textfield__input" required [(ngModel)]="model.username" name="username" type="text" id="username">
                <label class="mdl-textfield__label" for="username" >Username</label>
              </div>
              <br />
              <div class="text-field mdl-textfield mdl-js-textfield">
                <input class="mdl-textfield__input" [(ngModel)]="model.password" name="password" type="password" id="password">
                <label class="mdl-textfield__label" for="password">Password</label>
              </div>
              <br />
              <div class="text-field mdl-textfield mdl-js-textfield">
                <input class="mdl-textfield__input" [(ngModel)]="model.email" name="email" type="email" id="email">
                <label class="mdl-textfield__label" for="email">E-Mail</label>
              </div>
          </div>
          <div class="mdl-card__actions mdl-card--border">
            <button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">Registrieren</button>
          </div>
        </div>
        </form>
      </div>
    </div>
    <div class="mdl-layout-spacer"></div>
</div>

注册组件

import  Component  from '@angular/core';
import  User  from '../../objects/user';

@Component(
  selector: 'app-root',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.css']
)

export class RegisterComponent 
  model = new User(0, "", "", "");
  submitted = false;
  onSubmit() 
    console.log("PW" + this.model.password);
  

【问题讨论】:

有什么问题?路由仅向页面添加/删除组件。重新加载会重新初始化整个页面。 你的路由器插座在哪里? 【参考方案1】:

没有看到你的源代码就很难看出问题。

重新加载页面和使用路由器之间的简化区别是:

路由器将在标签内渲染路由。这允许您在页面中动态加载组件,而无需重新加载任何页面。 重新加载页面会导致重新加载整个页面,如果使用 AoT 编译,则成本要高得多。真的不需要重新加载,所有导航都应该在路由器中处理。

至于您的问题,您似乎正在多次加载该组件。如果您正在谈论与工具提示重叠的文本,这可能是您如何导入材料设计组件的依赖问题。发布您的代码,我会尽力帮助您。

【讨论】:

【参考方案2】:

所以,我假设您的问题是标签在重新加载之前与输入重叠。这与路由/重新加载无关(或者至少不是问题的根源)。你的材料设计精简版 JS 文件没有做他的工作!

我重新创建了问题here 并通过添加库here 解决了它。

这可能是由多种因素造成的:

MDL 在组件渲染后加载它的脚本。 您的 MDL.js 已损坏/无法正常工作。 您使用的第 3 部分库未正确链接。

如果您使用angular-cli,您需要将库添加到全局范围。为此,请在 .angular-cli.json 文件中添加库的路径:

...
"scripts": [
  "/assets/js/material.min.js",
  ...
]
...

【讨论】:

感谢您的回答,我将脚本和样式添加到 angular-cli,现在它无需在我的 index.html 中引用即可工作。但我仍然得到同样的错误。我用新版本替换了 MDL。 开发工具控制台上是否显示任何错误? 很遗憾没有,只是关于 angular2 的信息,因为它在开发模式下运行。【参考方案3】:

在动态渲染组件时,Material Design Lite 需要一些额外的工作。更多信息请关注their docs

TLDR; 您需要在元素被注入 DOM 后调用 componentHandler.upgradeElement。下面的示例描述了我过去使用的一种方法。

编辑如果您想要一个声明性解决方案this approach here 似乎是一个不错的解决方案,但我自己没有使用它。

我创建了一个包装 Material Lite 组件处理程序的服务

import  Injectable  from '@angular/core';

export interface ComponentHandler 
    upgradeDom();



declare var componentHandler: ComponentHandler;


@Injectable()
export class MaterialService 
    handler: ComponentHandler;
    constructor() 
        this.handler = componentHandler;
    

    // render on next tick
    render() 
        setTimeout(() =>  this.handler.upgradeDom(); , 0);
    


然后在组件将元素注入 DOM 后调用服务的渲染函数。

这是一个非常人为的例子,但演示了“在哪里”调用渲染

import  Component, OnInit  from '@angular/core';
import  DataService  from 'services/data.service';
import  MaterialService  from 'services/material.service';

@Component(
    selector: 'app-thing',
    templateUrl: `
       <ul>
            <li *ngFor="let item of data">
              data
            </li>
       </ul>
    `
)
export class ThingComponent implements OnInit 
    data: string[]
    constructor(
        private service: DataService,
        private material: MaterialService
    )  

    ngOnInit() 
        this.service.getData()
        .subscribe(data => 
            this.data = data;
            this.material.render();
        );
     

【讨论】:

以上是关于angular2 - 使用路由器问题的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据注入从路由器创建的 Angular2 组件中?

如何处理 angular2 延迟加载路由失败

使用 GraphQL 的 Angular2 服务和路由解析器

Angular2 + Nginx 深度链接/路由问题

Angular2 - 具有登录结构的路由器插座

如何在提交按钮表单中使用路由 - Angular2