前言
最近项目临近结束,没多少工单要做,就开始自学Redux,打算使用redux做一个组件间通讯的demo
一、官方文档
二、Action Reducer Store
1.核心概念
- state中存储数据,但是不可以修改。
- 要想修改state中存储的数据,需要发起一个action,action主要用来描述发生了什么,它的定义也比较语义化,
- 而实现数据修改主要靠reducer,reducer将state与action关联起来,通过一个函数改变state树(接收一个旧的state与action,通过判断action.type执行相应的处理,返回一个新的state)。
注意:当state变化时,需要返回全新的对象,而不是修改时传入的参数
2.快速上手
代码下载地址:https://github.com/fairyLiu-153/angular-redux
- npm install --save redux
- 这是一个非常简易的demo,但是对于理解利用redux来实现组件间通讯非常的有帮助。主要表现为:点击登录按钮,文字切换为hello Nancy! 点击退出按钮,文字切换为 请登录…
- 使用了三个组件,最外层父组件(蓝框),display组件(绿框),login组件(红框),点击按钮改变login的状态,display组件获取login状态来显示文字
- 文件目录如下(只需要看关于login的即可,to-do-list为下一个demo)
代码如下(完整代码):
1.login.action.ts: 只有一个type:SET_IS_LOGIN,布尔型
import { Action, ActionCreator } from 'redux';
export interface SetIsLoginAction extends Action {
login: boolean;
}
export const SET_IS_LOGIN = 'SET_IS_LOGIN';
export const setIsLogin: ActionCreator<SetIsLoginAction> = (login: boolean) => ({
type: SET_IS_LOGIN,
login
});
2.actions目录下index.ts:
import * as LoginActions from './login.action';
// import * as TodoListActions from './to-do-list.action';
export {
LoginActions,
//TodoListActions
}
3.login.reducer.ts:
import { SET_IS_LOGIN, SetIsLoginAction } from '../actions/login.action';
import { Reducer, Action } from 'redux';
export interface LoginState {
login: boolean;
}
const initialState: LoginState = {
login: false,
};
/* reducer改变状态树: 接收旧的state和action,返回新的state
(state, action)=> state
当state变化时,需要返回全新的对象,而不是修改传入的参数
*/
export const LoginReducer = function (state = initialState, action: Action) {
switch (action.type) {
case SET_IS_LOGIN:
const login = (action as SetIsLoginAction).login;
return Object.assign({}, state, { login });
default:
return state;
}
};
4.reducers目录下index.ts:
import { Reducer, combineReducers } from 'redux';
import { LoginState, LoginReducer } from './login.reducer';
export * from './login.reducer';
//import { ToDosState, ToDosReducer } from './to-do-list.reducer';
//export * from './to-do-list.reducer';
export interface AppState {
login: LoginState;
//toDoList: ToDosState;
}
export const rootReducer: Reducer<AppState> = combineReducers<AppState>({
login: LoginReducer,
//toDoList: ToDosReducer
});
5.redux.service.ts:
import { Injectable } from '@angular/core';
import { createStore, Store, Unsubscribe } from 'redux';
import { AppState, rootReducer} from './reducers';
import { LoginState } from './reducers/login.reducer';
import { ITodoItem, ToDosState } from './reducers/to-do-list.reducer';
import { TodoListActions, LoginActions } from './actions';
@Injectable({
providedIn: 'root'
})
export class ReduxService {
private store: Store<AppState>;
private unsubscribe: Unsubscribe;
constructor() {
// 创建redux store 来存放应用的状态
this.store = createStore(
rootReducer
);
}
// 读取状态
getIsLogin(): boolean {
const state: LoginState = this.store.getState().login;
return state.login;
}
// 改变内部state -> dispatch一个action
setIsLogin(login: boolean) {
this.store.dispatch(LoginActions.setIsLogin(login));
}
// 订阅更新
subscribeStore(readStateFun: () => void) {
this.unsubscribe = this.store.subscribe(readStateFun);
}
6.display.component.html:
<h1>使用Redux实现组件通讯</h1>
<span *ngIf="login">hello Nancy!</span>
<span *ngIf="!login">请登录...</span>
7.display.component.ts:
import { Component, OnInit } from '@angular/core';
import { ReduxService } from 'src/app/redux/redux.service';
@Component({
selector: 'app-display',
templateUrl: './display.component.html',
styleUrls: ['./display.component.scss']
})
export class DisplayComponent implements OnInit {
login: boolean;
constructor(
private reduxService: ReduxService
) { }
ngOnInit(): void {
this.reduxService.subscribeStore(() => this.readState());
this.readState();
}
readState() {
this.login = this.reduxService.getIsLogin();
}
}
8.login.component.html:
<div>
<button (click)="login()">登录</button>
</div>
<div>
<button (click)="logout()">退出</button>
</div>
9.login.component.ts:
import { Component, OnInit } from '@angular/core';
import { ReduxService } from 'src/app/redux/redux.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor(
private reduxService: ReduxService
) { }
ngOnInit(): void {
}
login() {
this.reduxService.setIsLogin(true);
}
logout() {
this.reduxService.setIsLogin(false);
}
}
总结
提示:这个demo非常简易,总体只是对login的状态进行获取和设置,登录状态还是退出状态,但是完成之后会对redux有一个新的认识,懂得写redux的基本步骤,查阅相关资料几乎很多都是基于React的,现angular简易小demo可参考。(初学者)