项目说明
现在主要是做React开发,也是使用服务端渲染(DEMO),最近想用Angular写一个项目体验一下TypeScript大法,对比Angular对比React从开发体验上来讲个人觉得更加方便很多东西不需要你自己去单独安装.
线上地址:https://music.soscoon.com
Github: https://github.com/Tecode/angular-music-player/tree/QQ-music
目前还在努力开发中,目前完成了80%…
预览图
技术栈
- Angular 7.2.0
- pm2 3.4.1
- better-scroll 1.15.1
- rxjs 6.3.3
- ngrx 7.4.0
- hammerjs 2.0.8
NgRx配置
Actions
和Vuex
,Redux
一样都需要先定义一些actionType,这里举了一个例子
src/store/actions/list.action.ts
import { Action } from '@ngrx/store';
export enum TopListActionTypes {
LoadData = '[TopList Page] Load Data',
LoadSuccess = '[TopList API] Data Loaded Success',
LoadError = '[TopList Page] Load Error',
}
// 获取数据
export class LoadTopListData implements Action {
readonly type = TopListActionTypes.LoadData;
}
export class LoadTopListSuccess implements Action {
readonly type = TopListActionTypes.LoadSuccess;
}
export class LoadTopListError implements Action {
readonly type = TopListActionTypes.LoadError;
constructor(public data: any) { }
}
合并ActionType
src/store/actions/index.ts
export * from './counter.action';
export * from './hot.action';
export * from './list.action';
export * from './control.action';
Reducers
存储数据管理数据,根据ActionType
修改状态
src/store/reducers/list.reducer.ts
import { Action } from '@ngrx/store';
import { TopListActionTypes } from '../actions';
export interface TopListAction extends Action {
payload: any,
index: number,
size: number
}
export interface TopListState {
loading?: boolean,
topList: Array<any>,
index?: 1,
size?: 10
}
const initState: TopListState = {
topList: [],
index: 1,
size: 10
};
export function topListStore(state: TopListState = initState, action: TopListAction): TopListState {
switch (action.type) {
case TopListActionTypes.LoadData:
return state;
case TopListActionTypes.LoadSuccess:
state.topList = (action.payload.playlist.tracks || []).slice(state.index - 1, state.index * state.size);
return state;
case TopListActionTypes.LoadErrhammerjsor:
return state;
default:
return state;
}
}
合并Reducer
src/store/reducers/index.ts
import { ActionReducerMap, createSelector, createFeatureSelector } from '@ngrx/store';
//import the weather reducer
import { counterReducer } from './counter.reducer';
import { hotStore, HotState } from './hot.reducer';
import { topListStore, TopListState } from './list.reducer';
import { controlStore, ControlState } from './control.reducer';
//state
export interface state {
count: number;
hotStore: HotState;
topListStore: TopListState;
controlStore: ControlState;
}
//register the reducer functions
export const reducers: ActionReducerMap<state> = {
count: counterReducer,
hotStore,
topListStore,
controlStore,
}
Effects
处理异步请求,类似于redux-sage redux-thunk
,下面这个例子是同时发送两个请求,等到两个请求都完成后派遣HotActionTypes.LoadSuccess
type到reducer
中处理数据.
当出现错误时使用catchError
捕获错误,并且派遣new LoadError()
处理数据的状态.
LoadError
export class LoadError implements Action {
readonly type = HotActionTypes.LoadError;
constructor(public data: any) { }
}
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { HotActionTypes, LoadError, LoadSongListError } from '../actions';
import { of, forkJoin } from 'rxjs';
import { HotService } from '../../services';
@Injectable()
export class HotEffects {
@Effect()
loadHotData$ = this.actions$
.pipe(
ofType