搭建angular项目
1.安装typescript (在这之前安装好node和淘宝镜像)
cnpm i -g typescript
2.安装angular脚手架
cnpm i -g angular-cli
第二次安装上面两步就不要了
3. ng new+项目名称
4. cd 项目名称
5.cnpm i 安装依赖
6.ng server/npm start
配置sass(本项目中使用sass,每个项目可根据实际情况来定)
1. 安装sass和loader
cnpm i node-sass --save-dev
cnpm i sass-loader --save--dev
2. 配置angular.json
"styles": [
"src/styles.scss"
],
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
3.然后在生成component时可以自动生成后缀名为.scss的文件
配置ng-zorro
1. npm i ng-zorro-antd --save
2.引入模块
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { NgModule } from '@angular/core';
import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd'
import { AppComponent } from './app.component';
import { HeaderComponent } from './share/components/header/header.component';
@NgModule({
declarations: [
AppComponent,
HeaderComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
NgZorroAntdModule.forRoot()
],
providers: [ { provide: NZ_I18N, useValue: zh_CN } ], // 配置ng-zorro-antd国际化
bootstrap: [AppComponent]
})
export class AppModule { }
3. 配置angular.json
"styles": [
"./node_modules/ng-zorro-antd/src/ng-zorro-antd.less",
"src/styles.scss"
],
配置路由
1. 添加AppRoutingModule
ng generate module app-routing --flat -module=app
--flat 把这个文件放进了src/app中,而不是单独的目录中
--module=app 告诉cli把它注册到AppModule的imports数组中
2. 添加路由定义
import { Routes } from '@angular/router';
import { environment } from '../environments/environment';
export const routes: Routes = [
{
path: 'login',
loadChildren: 'src/app/pages/login/login.module#LoginModule'
}
]
//route.ts这里是将路由定义作为一个文件引入
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { routes } from '../routes'; //这里引入routes的index.ts文件
import { environment } from '../environments/environment';
@NgModule({
imports: [RouterModule.forRoot(routes)],//初始化路由器,并让它开始监听浏览器中的地址变化
exports: [RouterModule]
})
export class AppRoutingModule { }
//app-routing.module.ts
3. 在app.component.html添加路由出口
<div class="main">
<router-outlet></router-outlet>
</div>
4. 每个组件也要配置路由
ng g m 组件名称 --routing
ng g c 组件名称
比如这里的login.module组件需要在login-routing.module.ts配置路由
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login.component';
const routes: Routes = [
{
path: '',
component: LoginComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class LoginRoutingModule { }
// login-routing.module.ts
配置服务
1. 创建一个服务
ng g serve 服务名称
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Res } from '../interfaces/res.interface';
@Injectable({
providedIn: 'root'
})
export class LoginService {
constructor(private http: HttpClient) { }
// 登录
public login(user): Observable<Res> {
return this.http.post<Res>('/api/user/login', user)
}
}
// login.service.ts
export interface Res<T = any> {
data: T
status: number
msg: string
}
//res.interface
2. 引入服务(在要使用服务的组件上)
比如import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoginRoutingModule } from './login-routing.module';
import { LoginComponent } from './login.component';
import { LoginService } from '../../share/serve/login.service'
@NgModule({
imports: [
CommonModule,
LoginRoutingModule,
ReactiveFormsModule
],
declarations: [
LoginComponent,
],
providers:[LoginService] //这里必须要写
})
export class LoginModule { }
//login.module.ts
3. 订阅服务
import { Component, OnInit } from '@angular/core';
import { FormBuilder,FormGroup } from '@angular/forms';
import { LoginService } from '../../share/serve/login.service';
import { NzMessageService } from 'ng-zorro-antd';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor(private fb: FormBuilder,
private loginServer: LoginService,
private msg: NzMessageService
) { }
public code: string = '';
public loginForm: FormGroup
ngOnInit() {
this.loginForm = this.fb.group({
username: [''],
password: [''],
authCode: ['']
})
// 得到验证码
this.loginServer.getAuthCode().subscribe(
(res) =>{
this.code = 'data:image/png;base64,' + res
}
)
}
// 订阅服务的具体步骤
public login(){
this.loginServer.login(this.loginForm.value).subscribe(
(res) =>{
const { data } = res
localStorage.setItem('token', data.token)
this.msg.info(res.msg);
}
)
}
}
// login.component.ts,这里简略地阐述下登录的过程.首先发起获取验证码的请求,将验证码渲染在页面上,然后提交登录信息,带上token发起login的请求
4. 配置代理
{
"/api": {
"target": "https://www.sceo360.com",
"changeOrigin": true,
"pathRewrite": {
"^/api": "/api"
}
}
}
// proxy.conf.json
{
"name": "http",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"dev": "ng serve --proxy-config=proxy.conf.json",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
// package.json
登录拦截器
import { Injectable } from '@angular/core'
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse,
} from '@angular/common/http'
import * as qs from 'qs'
import { Observable } from 'rxjs'
// import { AuthServiceService } from '../serves/auth-service/auth-service.service';
import { tap } from 'rxjs/operators'; //捕获请求的状态
import { Router } from '@angular/router';
import { environment } from '../environments/environment';
// import { SimpleReuseStrategy } from '../share/simple-reuse-strategy';
@Injectable()
export class SetTokenHeaderInterceptor implements HttpInterceptor {
constructor( private router: Router) {}
// intercept方法会把请求转换成一个最终返回HTTP响应的observeable.
// next对象表示拦截器链表中的下一个拦截器
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
const { body, method, headers } = req
const customerHeaders = {
'Content-Type': headers.get('Content-Type') || 'application/x-www-form-urlencoded'
}
// 在克隆请求的同时设置新请求头
const reqWithToken = req.clone({
setHeaders: customerHeaders,
body: method.toLocaleLowerCase() === 'post' || !headers.get('Content-Type') ? qs.stringify(body) : body
})
// 以便这个请求能走到下一个拦截器,并最终传给后端处理器
return next.handle(reqWithToken)
.pipe(
tap(
(event) => {
if (event instanceof HttpResponse) {
// console.log(event.body)
const { status } = event.body
switch(status) {
case 400:
environment.production && (location.href = '/login')
// 清空所有缓存路由
// SimpleReuseStrategy.handlers = {}
break;
}
}
}
)
)
}
}
// set-token-header-interceptor.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http'
// 设置token请求头
import { SetTokenHeaderInterceptor } from './set-token-header-interceptor'
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: SetTokenHeaderInterceptor, multi: true }
]
// index.ts
然后再根组件中引入
网友评论