为什么需要redux?
-
随着JavaScript开发的应用程序,变得越来越复杂,javaScript需要管理的状态越来越多,越来越复杂。
- 这些状态包括服务器返回的数据、缓存数据、用户操作产生的数据等等,包括一些UI的状态,比如某些元素是否被选中,是否显示或者隐藏一些元素。
-
这些状态变化不断,一个状态的变化可能会引起另一个状态变化。
Redux就是一个帮助我们管理state的容器:Redux是javaScript的状态容器,提供了可预测的状态管理。
Redux核心理念
store(仓库)
把数据(状态state)放到仓库中管理
action(行为)
redux要求通过action来更新数据:
- 必须通过派发(dispatch)action来修改数据
- action包括type和content
store.dispatch({type:"change_name",name:"kobe"})
reducer
负责将state和action联系在一起的,他是一个纯函数,返回一个新的state
// reducer就是要返回一个新的state
function reducer(state,action){
return newState;
}
Redux的三大原则
- 单一数据源,整个应用程序的state只存储到一个store,多个store不利于数据的维护
- state是只读的,修改state的唯一方法是触发action
- 使用纯函数来修改,所有的reducer都应该是纯函数,不能产生副作用。
Redux项目搭建
安装:
// npm的初始化操作
npm init -y
npm install redux
// yarn的初始化操作
yarn init -y
yarn add redux
使用过程
-
创建一个对象作为要保存的状态
// 在store.js中定义一个初始化的状态 const initialState = { name: "kobe"; } -
创建store来存储这个state
// 导入createStore const { createStore } = require("redux"); // 错误写法 const store = createStore(initialState);- 但是createStore()函数要求传入一个reducer
-
声明一个reducer函数,传入createStore函数中
function reducer(){ return initialState } const store = createStore(reducer); // 导出 store module.exports = store; -
在其他页面来获取state
// 在index.js中 const store = require("./store") // 通过store.getState 来获取当前的state console.log(store.getState()); // 打印结果 // { name: 'kobe' } -
通过action来修改state
- 通过dispatch来派发action
- 通常action中都会有type属性,也可以携带其他数据
// index.js const store = require("./store") // 错误的写法 store.getState().name = "james" // 不能这么写,只能通过dispatch派发action来修改 const changeNameAction = {type:"change_name",name:"james"}; store.dispatch(nameAction); // 再次获取state console.log(store.getState()); // 打印结果 // { name: "james" } -
修改reducer函数中的代码
/* 接受两个参数: 参数1:store中目前保存的state 参数2:dispatch传递的action(本次需要更新的action) 返回值:作为store之后存储的state */ function reducer(state,action){ switch(action.type){ case "change_name": return {...state,name:action.name}; default: return state; } } -
监听store的变化
// 我们不用在state发生变化后,每次通过store.getState来获取state // 通过订阅来监听state的变化 const unsub = store.subscribe(()=>{ console.log("订阅数据变化:",store.getState()); }) // 调用函数取消监听 unsub();这样也会有一个小问题,第一次打印的时候state是一个undefined
-
给reducer函数的入参state一个默认值
function reducer(state = initialState,action){ switch(action.type){ case "change_name": return {...state,name:action.name}; default: return state; } }
Redux结构优化
如果我们将所有的逻辑代码写到一起,那么当redux变得复杂时,代码就难以维护。
接下来对代码进行拆分,将store、reducer、action、constants拆分成一个个文件。
store/index.js
const { createStore } = require("redux");
const reducer = require("./reducer");
const store = createStore(reducer);
module.exports = store;
store/reducer.js
const { CHANGE_NAME } = require("./constants");
const initialState = {
name: "kobe",
};
function reducer(state = initialState, action) {
switch (action.type) {
case CHANGE_NAME:
return { ...state, name: action.name };
default:
return state;
}
}
module.exports = reducer;
store/actionCreator.js
const { CHANGE_NAME } = require("./constants");
const changeNameAction = (name) => ({
type: CHANGE_NAME,
name,
});
module.exports = {
changeNameAction,
}
store/constants.js
const CHANGE_NAME = "change_name";
module.exports = {
CHANGE_NAME
}
以上我们做的优化有这么几点:
- 将派发的action生成过程放到一个actionCreator函数中
- 又将actionCreator函数放到一个独立的文件中,以后所有创建action都放在这里
- 将reducer函数和actionCreator函数都用到的字符串,声明常量放到一个单独的constants文件中
- 将reducer和默认初始状态放到一个独立的文件中。
Redux使用流程
以上全部,谢谢!