Redux简介

一. 直接管理状态

直接管理状态的方式

从服务中获取数据,然后在组件中渲染数据,通过组件树从上到下传递所有值。使用Angular默认的变更检测机制,每当有任一组件变化时,都会检测整个组件树。

直接管理状态的缺点

  • 属性的间接传递
  • 重构不灵活
  • 状态树和DOM树不匹配
  • 应用中到处都是状态

二. Redux

Redux:一种现今十分流行的数据结构。其最大优点可能是它的简单性。如果把Redux剥离的只剩核心代码,其代码行数将不到100行。
Redux Primer-Flux:单向流
Redux模式
事件流
状态流


核心概念

  • 应用的所有数据都存放在一个叫做state的数据结构之中,而state存放在store中。
  • 应用从store中读取state
  • store永远不会被直接修改
  • action描述发生了什么,由用户交互触发
  • 通过调用一个叫做reducer的函数来结合旧的state和action创建出新的state
    Redux内核

主要元素

store
  • 保存应用当前状态的一个实例对象
  • 存储的是任何时候应用唯一的状态
  • 负责运行reducer然后保存新的state
  • 每个store都和一个特定的reducer紧密相关。使用私有变量来存储它

常用方法:createStore subscribe dispatch getState
- createStore: 创建一个store的实例对象;
- getState: 返回当前的state变量;
- dispatch: 接收一个action并把它传给reducer,然后用reducer的返回值来更新state变量的值。注意,该方法没有返回值,是一种“触发并忘记”的策略;
- subscribe: 用此方法来注册一个监听函数;当dispatch被调用时,我们遍历所有的监听器并逐个调用它们,它们会负责通知大家这 个state发生了变化。 返回一个unsubscribe函数。

小例子:

//定义store类
class Store<T> {

private _state: T;
private _listeners: ListenerCallback[] = [];

constructor(
private reducer: Reducer<T>,
initialState: T
) {
this._state = initialState;
}

getState(): T {
return this._state;
}

dispatch(action: Action): void {
this._state = this.reducer(this._state, action);
this._listeners.forEach((listener: ListenerCallback) => listener());
}

subscribe(listener: ListenerCallback): UnsubscribeCallback {
this._listeners.push(listener);
return () => { // returns an "unsubscribe" function
this._listeners = this._listeners.filter(l => l !== listener);
};
} }


//使用store类
let store = new Store<number>(reducer, 0);
console.log(store.getState()); // -> 0
// subscribe
let unsubscribe = store.subscribe(() => {
console.log('subscribed: ', store.getState());
});
store.dispatch({ type: 'INCREMENT' }); // -> subscribed: 1
store.dispatch({ type: 'INCREMENT' }); // -> subscribed: 2
unsubscribe();
store.dispatch({ type: 'DECREMENT' }); // (nothing logged)
// decrement happened, even though we weren't listening for it
console.log(store.getState()); // -> 1

provideStore 提供给我们一个应用存储在应用的生命周期中使用。


action
  • 描述发生了什么改变,由用户交互触发
  • 结构:{type:string;payload?:any}
  • 通常命名是自定义的字符串,建议全部使用大写
  • 表示type字符串的变量应声明为static,以便可通过类名直接访问,如static QUEUE = '[NOW PLAYLIST] QUEUE';
  • 做为store的dispatch()的参数被使用

action creators:用于创建action的函数。因为直接使用action做为参数时,dispatch语句都不够优雅,原因有以下两点:

  • 不再需要手动转换相应的Action类型。
  • 如果终决定要改变payload的格式,我们不用更新任何一处dispatch 语句。

一个简单的actionCreator函数:

updateName(name: string): Action {
return {
type: "UPDATE_NAME",
payload: name
};
}
// usage
this.store.dispatch(updateName("oren"))

reducer
  • 不能直接修改state,只能返回一个新的state为什么不能直接修改state
  • 必须是一个纯函数,不会使用参数之外的任何数据
    注:纯函数在参数不变的情况下,总是会返回同一个值;而且纯函数不会调用任何对外界产生影响的函数。纯函数
  • 通常采用switch/case结构,default返回原来的state(当传入一个未知的action时,这确保程序不会报错而我们能得到原始的state值)
  • 经常需要将reducer分解成若干个sub-reducer,它们各自管理state树中的一个不同分支,使用combineReducer(),可参考reducer分解

生成新的state通常有四种操作:

  • 往数组中添加一项
    array.concat()
  • 从数组中移除一项
    array.slice()
  • 添加对象中的键或修改对象中某些键的值
    Object.assign({}, state, { name: action.payload })
  • 从对象中移除键
    Object.assign({},{logged_in:false,name:''})
    javascript array方法

一个reducer实例:

export function user (state = {}, action: Action):ActionReducer<IUser> {
switch (action.type) {
case "UPDATE_NAME":
return Object.assign({}, state, { name: action.payload });
case "LOG_OUT":
return Object.assign({}, {
logged_in: false,
name: ''
});
default:
return state;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值