目录
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
this.$store.commit('set_num');
this.$store.commit('模块名/set_num');
this.$store.commit('set_num',参数...);
actions:处理异步 -await this.$store.dispatch('模块名/set_num')
mapState 辅助函数映射 Vuex 的状态到Vue实例上,可通过this.直接访问
将Vuex的状态持久化到本地存储中,解决页面刷新或重新打开应用时状态丢失的问题
状态管理库
// 创建全局变量
window.globalVariable = '这是一个全局变量';
单一事实来源:存储更新所有组件状态
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 和 getters
modules: {
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修改state
switch(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,分发action
type: '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>
);