目录
状态管理库
单一事实来源:存储更新所有组件状态
Vuex
安装
配置
src->store
index:拆分模块modules
vue2
vue3
main
index【以Conversation模块为例】【拆分state等属性】
store state() { return state; }类似于
vue中data() return{数据对象}:多个组件实例时,新建(return{})/引用同一个(:{})
this.$store=store(工具文件中,如Util.ts)
state:原生读this.$store.state.XXX
Getter:修饰读this.$store.getters.XXX
getter 的参数化
mutations :同步修改
this.$store.commit('set_num');
this.$store.commit('模块名/set_num');
this.$store.commit('set_num',参数...);
函数起名
set_stateNm(局部)
SET_stateNm(全局)
参数类型起名
map
value
payload传递对象
actions:处理异步 -await this.$store.dispatch('模块名/set_num')
内部commit
【官方建议】
读/修饰状态放在computed
mapState 辅助函数映射 Vuex 的状态到Vue实例上,可通过this.直接访问
单模块
多模块
mapGetters
mapMutations:methods
mapActions
状态持久化:vuex-persistedstate插件
将Vuex的状态持久化到本地存储中,解决页面刷新或重新打开应用时状态丢失的问题
Redux
组件
与Vuex区别
使用
状态管理库
// 创建全局变量
window.globalVariable = '这是一个全局变量';
单一事实来源:存储更新所有组件状态
Vuex
图来自What is Vuex? | Vuex
安装
npm install vuex --save
配置
src->store
index:拆分模块modules
vue2
import Vue from 'vue';
import Vuex from 'vuex';
import Conversation from './Conversation';
import App from './App';//通过 Vue 插件安装 Vuex,并且在全局注册 this.$store,使得在所有组件中都可以访问到 Vuex 的功能
Vue.use(Vuex);export default new Vuex.Store({
//modules:是一个配置项,用于定义各个模块。
//拆分成多个模块,每个模块可以包含自己的 state、mutations、actions 和 gettersmodules: {Conversation,App,},
});
vue3
import { createApp } from 'vue';
import { createStore } from 'vuex';const store = createStore({// 配置
});const app = createApp(App);
app.use(store);
app.mount('#app');
main
import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store'; // 引入我们前面导出的store对象Vue.config.productionTip = false;new Vue({el: '#app',router,store, // 把store对象添加到vue实例上components: { App },template: '<App/>',
});
index【以Conversation模块为例】【拆分state等属性】
store state() { return state; }类似于
vue中data() return{数据对象}:多个组件实例时,新建(return{})/引用同一个(:{})
this.$store=store(工具文件中,如Util.ts)
import state from './state';
import actions from './actions';
import getters from './getters';
import mutations from './mutations';const store = {
//namespaced: true 可以帮助区分不同模块中的 actions、mutations 和 getters,避免了命名冲突namespaced: true,state() {return state;},getters,mutations,actions,
};export default store;
state:原生读this.$store.state.XXX
this.$store.state.Conversation.moveConversationList
import LRU from 'lru-cache';
import IMGlobalUtil from '@/util/appconfig';});
// 缓存用户相关的群组基本信息,每条大约640个字符,最多缓存1000条
const groupsCache = new LRU({max: IMGlobalUtil.groupsCacheNumber * 640,
});const state = {summaryMsgMap:{},groups: groupsCache,
};export default state;
Getter:修饰读this.$store.getters.XXX
如果模块名称包含特殊字符或者动态获取 getter 名称时,就需要使用数组语法
this.$store.getters['Conversation/searchGroup'](this.search_value);
getter 的参数化
第一个箭头函数作为 Vuex getter 的定义部分,它可以访问到
state
和getters
,并且将参数传递给第二个箭头函数。
- 第二个箭头函数则形成了一个闭包,可以访问外部函数(第一个箭头函数)的作用域中的
state
和getters
const getters = {//消息未读数totalUnReadNum: (state: any, getters: any) => {return state.totalUnReadNum;},//模糊搜索群组searchGroup: (state: any, getters: any) => (str: any) => {let reg = /^[0-9a-zA-Z\-]+$/;str = str.trim();let newArr: any = [];if (str !== '') {state.groups.keys().forEach((key: any) => {let item = state.groups.get(key);if (item.name.indexOf(str) !== -1) {newArr.push(item);}});}return newArr;},//获取群组中某个成员getGroupMember: (state: any, getters: any) => (groupId: any, memberId: any) => {let group = state.groups.get(groupId);if (group && group.memberMap) {return group.memberMap[memberId];}},
};export default getters;
mutations
:同步修改
this.$store.commit('set_num');
this.$store.commit('模块名/set_num');
this.$store.commit('set_num',参数...);
函数起名
set_stateNm(局部)
SET_stateNm(全局)
参数类型起名
map
value
payload传递对象
const mutations = {set_transforMap(state:any,map:any){let length = Object.keys(state.transforMap).length;//最多存100条if(length > 100){state.transforMap = {...map}}else{state.transforMap = { ...state.transforMap, ...map };}},set_lastMsgAi(state: any, value: any) {state.lastMsgAi = value;},set_urgencyList(state: any, payload: any) {state.urgencyList = payload;},//更新网络状态UPDATE_NET_STATUS(state: any, value: any) {state.netStatus = value;},
};export default mutations;
actions:
处理异步 -await this.$store.dispatch('模块名/set_num')
内部commit
方法的形参可以直接将commit解构出来
import * as sessionGroupServer from '@/server/sessionGroup';
const actions = {update_sessionGroupList({ state, commit }: any) {sessionGroupServer.getGrouping().then((res: any) => {if (res && res.length) {commit('set_sessionGroupList', res);if (!res.find((item: any) => {return item.groupingKey == state.curSessionGroupKey;})) {commit('set_curSessionGroupKey', 'MIS_grouping_all');}}});},set_bpm_number({commit}:any){bpmNumber().then((res:any)=>{if(res){commit("set_bpm_number",res)}}) },async set_app_info({commit}:any){let res = await getAppList(1,100);if(res){commit("set_app_info",res)}// getAppList(1,100).then((res:any)=>{// if(res){// commit("set_app_info",res)// }// })}
};export default actions;
【官方建议】
读/修饰状态放在computed
当 Vuex 中的状态发生变化时,computed 属性会自动更新。这避免了手动监听状态变化并进行手动更新的操作
computed: {userName() {return this.$store.state.user.name;}
}
mapState
辅助函数映射 Vuex 的状态到Vue实例上,可通过this.直接访问
单模块
computed: {...mapState(['name']), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它...mapState({ aliasName: 'name' }), // 赋成别名aliasName,这里接收对象,而不是数组}
多模块
//Conversation 模块中的 state.videoMeetingData 映射为当前组件的 videoMeetingData 计算属性。
...mapState('Conversation', {videoMeetingData: (state: any) => state.videoMeetingData,
})
mapGetters
...mapGetters(['getMessage']),
...mapGetters({ aliasName: 'getMessage' }), // 赋别名的话,这里接收对象,而不是数组
mapMutations:methods
<script>
import { mapMutations } from 'vuex';
export default {methods: {// 注意,mapMutations是解构到methods里面的,而不是计算属性了...mapMutations(['setNumberIsWhat']),},
};
</script>
mapActions
import { mapActions } from 'vuex';async mounted() {await this.setNum({ number: 123 }); // 直接这样调用即可},...mapActions({ setNumAlias: 'setNum' }), // 赋别名的话,这里接收对象,而不是数组
状态持久化:vuex-persistedstate插件
将Vuex的状态持久化到本地存储中,解决页面刷新或重新打开应用时状态丢失的问题
Redux
redux相当于在顶层组件之上又加了一个组件
组件
- Action 这是一个用来描述发生了什么事情的对象
- Reducer 这是一个确定状态将如何变化的地方
- Store 整个程序的状态/对象树保存在 Store 中
- View 查只显示 Store 提供的数据
与Vuex区别
Redux比较独立,可以跟很多框架结合使用,不过主要还是跟React配合比较好,也是最常见的React状态管理的库。
在 Vuex 中,有类似于 Redux 的 action 的概念,
但状态变更是通过称为 mutations 的同步函数来处理的,而异步逻辑则需要放在 action 中处理。
使用
//state存储共享数据
function counterReducer(state={count: 0}, action) {//reducer修改stateswitch(action.type){case 'inc':return {count: state.count + state.payload}default:return state;}
}
const store = createStore(counterReducer)
export default store
这样store对象就可以在其他组件中进行使用了,例如在<Bar>组件中。
import React from 'react'
import './Bar.scss'
import { useSelector,useDispatch } from 'react-redux'
export default function Bar() {const count = useSelector((state)=> state.count)//获取共享状态const dispatch=useDispatch();//修改共享状态const handleClick = () => {dispatch({//dispatch触发Reducer,分发actiontype: 'inc',payload: 5})}return (<div><button onClick={handleClick}>修改count</button> Bar, { count }</div>)
}
在主模块中进行注册。
import { RouterProvider } from 'react-router-dom'
import router from './router';
import { Provider } from 'react-redux'
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><Provider store={store}>//注册状态管理与React结合,自动完成重渲染<RouterProvider router={router}></RouterProvider></Provider></React.StrictMode>
);