@H_
502_0@
前言
@H_
502_0@Redux是迄今为止创建的最重要的JavaScript库之一,灵感来源于以前的艺术比如
Flux和
Elm,Redux通过引入一个包含三个简单要点的可伸缩体系结构,使得JavaScript
函数式编程成为可能。如果你是初次接触Redux,可以考虑先阅读
官方文档。
@H_
502_0@
1. Redux大多是规约
@H_
502_0@考虑如下这个使用了Redux架构的简单的计数器应用。如果你想跳过的话可以直接查看
Github Repo。
@H_
502_0@
1.1 State存储在一棵树中
@H_
502_0@该应用程序的状态看起来如下:
const initialState = { count: 0 };
@H_
502_0@
1.2 Action声明状态更改
@H_
502_0@根据Redux规约,我们不直接
修改(突变)状态。
// 在Redux应用中不要做如下操作
state.count = 1;
@H_
502_0@相反,我们创建在应用中
用户可能用到的所有行为。
const actions = {
increment: { type: 'INCREMENT' },decrement: { type: 'DECREMENT' }
};
@H_
502_0@
1.3 Reducer解释行为并更新状态
@H_
502_0@在最后一个架构部分我们叫做Reduer,其作为一个纯
函数,它基于以前的状态和行为返回状态的新副本。
- 如果increment被触发,则增加state.count
- 如果decrement被触发,则减少state.count
const countReducer = (state = initialState,action) => {
switch (action.type) {
case actions.increment.type:
return {
count: state.count + 1
};
case actions.decrement.type:
return {
count: state.count - 1
};
default:
return state;
}
};
@H_
502_0@
1.4 目前为止还没有Redux
@H_
502_0@你注意到了吗?到目前为止我们甚至还没有接触到Redux库,我们仅仅只是创建了一些对象和
函数,这就是为什么我称其为"大多是规约",90%的Redux应用其实并不需要Redux。
@H_
502_0@
2. 开始实现Redux
@H_
502_0@要使用这种架构,我们必须要将它放入到一个store当中,我们将仅仅实现一个
函数:createStore。使用方式如下:
import { createStore } from 'redux'
const store = createStore(countReducer);
store.subscribe(() => {
console.log(store.getState());
});
store.dispatch(actions.increment);
// logs { count: 1 }
store.dispatch(actions.increment);
// logs { count: 2 }
store.dispatch(actions.decrement);
// logs { count: 1 }
@H_
502_0@下面这是我们的初始化样板
代码,我们需要一个监听器列表listeners和reducer提供的初始化状态。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined,{});
}
@H_
502_0@无论何时某人
订阅了我们的store,那么他将会被
添加到listeners数组中。这是非常重要的,因为每次当某人在派发(dispatch)一个动作(action)的时候,所有的listeners都需要在此次事件循环中被
通知到。
调用yourReducer
函数并传入一个undefined和一个空对象将会返回一个initialState,这个值也就是我们在
调用store.getState()时的返回值。既然说到这里了,我们就来创建这个
方法。
@H_
502_0@
2.1 store.getState()
@H_
502_0@这个
函数用于从store中返回最新的状态,当
用户每次点击一个按钮的时候我们都需要最新的状态来更新我们的视图。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined,{});
return {
getState: () => currentState
};
}
@H_
502_0@
2.2 store.dispatch()
@H_
502_0@这个
函数使用一个action作为其入参,并且将这个action和currentState反馈给yourReducer来
获取一个新的状态,并且dispatch
方法还会
通知到每一个
订阅了当前store的监听者。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined,{});
return {
getState: () => currentState,dispatch: (action) => {
currentState = yourReducer(currentState,action);
listeners.forEach((listener) => {
listener();
});
}
};
};
@H_
502_0@
2.3 store.subscribe(listener)
@H_
502_0@这个
方法使得你在当store接收到一个action的时候能够被
通知到,可以在这里
调用store.getState()来
获取最新的状态并更新UI。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined,action);
listeners.forEach((listener) => {
listener();
});
},subscribe: (newListener) => {
listeners.push(newListener);
const unsubscribe = () => {
listeners = listeners.filter((l) => l !== newListener);
};
return unsubscribe;
}
};
};
@H_
502_0@同时subscribe
函数返回了另一个
函数unsubscribe,这个
函数允许你当不再对store的更新感兴趣的时候能够取消
订阅。
@H_
502_0@
3. 整理代码
@H_
502_0@现在我们
添加按钮的逻辑,来看看最后的源
代码:
// 简化版createStore函数
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined,subscribe: (newListener) => {
listeners.push(newListener);
const unsubscribe = () => {
listeners = listeners.filter((l) => l !== newListener);
};
return unsubscribe;
}
};
};
// Redux的架构组成部分
const initialState = { count: 0 };
const actions = {
increment: { type: 'INCREMENT' },decrement: { type: 'DECREMENT' }
};
const countReducer = (state = initialState,action) => {
switch (action.type) {
case actions.increment.type:
return {
count: state.count + 1
};
case actions.decrement.type:
return {
count: state.count - 1
};
default:
return state;
}
};
const store = createStore(countReducer);
// DOM元素
const incrementButton = document.querySelector('.increment');
const decrementButton = document.querySelector('.decrement');
// 给按钮添加点击事件
incrementButton.addEventListener('click',() => {
store.dispatch(actions.increment);
});
decrementButton.addEventListener('click',() => {
store.dispatch(actions.decrement);
});
// 初始化UI视图
const counterDisplay = document.querySelector('h1');
counterDisplay.innerHTML = parseInt(initialState.count);
// 派发动作的时候跟新UI
store.subscribe(() => {
const state = store.getState();
counterDisplay.innerHTML = parseInt(state.count);
});
@H_
502_0@我们再次看看最后的视图
效果:
@H_
502_0@

@H_
502_0@
总结
@H_
502_0@以上就是这篇
文章的全部
内容了,希望本文的
内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的
支持。
@H_
502_0@原文:
https://www.freecodecamp.org/news/redux-in-24-lines-of-code/
@H_
502_0@作者:Yazeed Bzadough
@H_
502_0@译者:小维FE