Redux相关
一 、Redux
1、Store
个人理解Store是redux的核心,通过createStore创建store,并通过store的函数操作里面的数据,如dispacth。
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()));
store.dispatch(actions.increase()); // {count: 1}
store.dispatch(actions.increase()); // {count: 2}
store.dispatch(actions.increase()); // {count: 3}
2、Action
个人理解action是判定进行哪些操作的行为。其中根据type选项,筛选Reducer中执行那些操作
export const actions = {
increase: () => ({ type: "INCREASE" }),
decrease: () => ({ type: "DECREASE" })
};
3、Reducer
reducer接收state和action,返回新的state,state是redux的数据。reducer主要是通过筛选目标action执行相关数据操作并更新state。
const reducer = (state = { count: 0 }, action: { type: any }) => {
switch (action.type) {
case "INCREASE":
return { count: state.count + 1 };
case "DECREASE":
return { count: state.count - 1 };
default:
return state;
}
};
二、react-redux
Provider
个人理解,通过Provider组件把store导入到子组件中,可以在子组件中接受到相关数据。
import { Provider } from "react-redux";
import { store } from "./redux/store";
...
<Provider store={store}>
<App a="1"></App>
</Provider>
...
connect()
个人理解,connect接收两个参数,mapStateToProps,mapDispatchToProps,第一个参数mapStateToProps(名称可变)目的是从store中获取参数映射到props中,第二个参数是将dispatch也封装函数导入到props直接使用
import { connect } from "react-redux";
const mapStateToProps = (state: any) => {
return {
// prop : state.xxx | 意思是将state中的某个数据映射到props中
foo: state.count
};
};
const mapDispatchToProps = (dispatch: any) => {
return {
increase: () => {
dispatch({
type: "INCREASE"
});
}
};
};
const UseRedux = (props: any) => {
return (
<>
<p>{props.foo}</p>
<button onClick={props.increase}>increase</button>
</>
);
};
export default connect(mapStateToProps, mapDispatchToProps)(UseRedux);
useSelector
通过useSelector直接拿到store中的数据
import { useSelector } from "react-redux";
export default () => {
const { value } = useSelector((store: any) => {
return store.counter;
});
return (
<>
<p>{value}</p>
</>
);
};
useDispatch
通过useDispatch返回dispatch函数
import { counterSlice } from "../redux/tookit";
const { increment, decrement } = counterSlice.actions;
import { useDispatch } from "react-redux";
export default () => {
const dispatch = useDispatch();
return (
<>
<button onClick={() => dispatch(increment())}>increment</button>
</>
);
};
useStore
通过useStore返回useStore对象
const store = useStore();
三、Redux Toolkit
Redux Toolkit简化了redux开发流程
createReducer
帮你将 action type 映射到 reducer 函数,而不是编写 switch...case 语句。另外,它会自动使用 [immer 库]
const initialState: CounterState = {
value: 0,
title: "redux toolkit pre"
};
// 创建一个 Slice
export const counterSlice = createSlice({
name: "counter",
initialState,
// 定义 reducers 并生成关联的操作
reducers: {
// 定义一个加的方法
increment: (state) => {
state.value += 1;
},
// 定义一个减的方法
decrement: (state) => {
state.value -= 1;
}
}
});
configureStore
封装了createStore,简化配置项,提供一些现成的默认配置项。它可以自动组合 slice 的 reducer,可以添加任何 Redux 中间件,默认情况下包含 redux-thunk,并开启了 Redux DevTools 扩展。
// configureStore创建一个redux数据
const store = configureStore({
// 合并多个Slice
reducer: {
counter: counterSlice
}
});
configureStore():封装了createStore,简化配置项,提供一些现成的默认配置项。它可以自动组合 slice 的 reducer,可以添加任何 Redux 中间件,默认情况下包含redux-thunk,并开启了 Redux DevTools 扩展。createReducer()帮你将 action type 映射到 reducer 函数,而不是编写 switch...case 语句。另外,它会自动使用immer库来让你使用普通的 mutable 代码编写更简单的 immutable 更新,例如state.todos[3].completed = true。createAction()生成给定 action type 字符串的 action creator 函数。该函数本身已定义了toString(),因此可以代替常量类型使用。createSlice()接收一组 reducer 函数的对象,一个 slice 切片名和初始状态 initial state,并自动生成具有相应 action creator 和 action type 的 slice reducer。createAsyncThunk: 接收一个 action type 字符串和一个返回值为 promise 的函数, 并生成一个 thunk 函数,这个 thunk 函数可以基于之前那个 promise ,dispatch 一组 type 为pending/fulfilled/rejected的 action。createEntityAdapter: 生成一系列可复用的 reducer 和 selector,从而管理 store 中的规范化数据。createSelector来源于 Reselect 库,重新 export 出来以方便使用。
四、redux-thunk(感觉没必要)
redux-thunk目的是将dispatch原本只能接受object数据,扩展了一些,可以传输函数。 功能:
const mapDispatchToProps = (dispatch: any) => {
return {
useThunk: () => {
dispatch(() => {
setTimeout(() => {
dispatch({
type: "USETHUNK"
});
}, 1000);
});
}
};
};
源码相当于
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) =>
(next) =>
(action) => {
if (typeof action === "function") {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware(null);
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
vuex
vuex核心概念
State
State是vuex的数据源,所有共享的数据统一放到store的state进行储存,相似与data。
const state = {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: []
}
使用方法
- 1、
this.$store.state.settings.theme - 2、使用mapState混入到computed
import { mapState } from 'vuex'
····
computed: {
...mapState({
sidebar: state => state.app.sidebar,
device: state => state.app.device
}),
},
····
Mutation
mutation是同步修改数据,更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。mutation里面包含修改state的具体函数操作。
const mutations = {
CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 0)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
TOGGLE_DEVICE: (state, device) => {
state.device = device
},
SET_SIZE: (state, size) => {
state.size = size
Cookies.set('size', size)
}
}
Action
Action异步修改数据,actions中可以进行异步操作,然后调用mutation间接变更state。
const actions = {
toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
closeSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
toggleDevice({ commit }, device) {
commit('TOGGLE_DEVICE', device)
},
setSize({ commit }, size) {
commit('SET_SIZE', size)
}
}
Getter
相当于计算属性,虽然组件component中有computed,但是getter可以再多个组件复用
const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permission_routes: state => state.permission.routes,
errorLogs: state => state.errorLog.logs
}
调用方式this.$store.getters.errorLogs
Modules
Modules即模块,为了解决数据量大store会显得很臃肿问题,所以store可以分割为module,每个模块拥有自己的 state、mutation、action、getter、甚至是可以嵌套子模块。 以下为整合modules并生成store。
// 导入各个module文件
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})