前言
我们都知道,vuex 的使用在项目中颇为繁琐,因为它有几大概念使得它不能像普通 ref 或者 data 对象一样直接被我们使用,在我们想要更改 vuex 中的数据时,我们需要通过 mutation 来进行提交,获取 vuex 中存储的变量的时候,我们又需要通过 computed 属性来进行声明,试想,如果项目足够庞大,那么我们使用 vuex 的负担就过于重了,这违背了我们使用状态管理的本意。
问题的提出
首先,我们需要明确,我们想要怎么快捷便利地来使用 vuex ,如果你的想法和我如下所示相同,那么恭喜你,或许本文提出的解决方案适合你。
存储
对于 vuex 的存储我们想要实现的类似如下:
this.$m.vuex(name,value);
我们可以在各个组件或者视图内,通过 this 来直接使用 vuex 进行存储。
读取
对于 vuex 中数据的读取我们想要实现的类似如下:
<template>
<div>{{ vuexUser.name }}</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
...
methods:{
// 业务方法
xxxxx(){
const flag = this.vuexUser.name? true : false;
.....
}
}
})
</script>
我们能够在模板或者业务逻辑中直接通过 this 直接访问。
解决方案
首先,我们需要在 store 目录下的 index.ts 内加入如下代码
import { createStore } from 'vuex'
export default createStore({
state: {
vuexIsLogin: false, // 当前的登录状态
vuexTestVar: "测试变量",
vuexUser:{
test: 1,
name: "WuYunLong"
}
},
mutations: {
$changeStore(state: any, payload: any){
// 判断是否为多层级调用
const nameArr = payload.name.split('.');
const len = nameArr.length;
if ( len >= 2){
let obj = state[nameArr[0]];
for (let i = 1 ; i < len - 1 ; i++){
obj = obj[nameArr[i]];
}
obj[nameArr[len-1]] = payload.value;
}else {
state[payload.name] = payload.value;
}
}
}
})
之后我们在 store 目录下创建一个 ts 脚本文件,在我的项目中我命名为 maxer.mixin.ts ,在这里,我们就需要使用 Vue 中的一个特性 Mixin(混入)「不明白的同学可以去官方文档查一查,Vue3 的官方中文版已经推出了」
/**
* @作者: WuYunlong
* @时间: 2021/06/22
* @版本: V1.0
* @说明: maxer Vue 全局混入
*/
import { App } from 'vue'
import { mapState } from "vuex";
import store from '@/store/index.ts'
// 将定义的state变量key全部加载到全局变量中
const $mStoreKey = store.state ? Object.keys(store.state) : [];
export class Maxer{
vuex = (name: string, value: any): void=>{
store.commit('$changeStore', {
name, value
})
}
}
export default<T> (app: App<T>) => {
// 进行全局混入
// 将vuex方法挂载到$m中
// 使用方法为: this.$m.vuex('user.name', 'x')
app.config.globalProperties.$m = new Maxer();
app.mixin({
computed: {
// 将vuex的state中的所有变量,解构到全局混入的mixin中
...mapState($mStoreKey)
}
})
}
在这里我们使用全局混入,将 vuex 的 state 混入到计算属性中,我们就可以通过类似 this.vuexName 来进行调用,还有一点建议就是,由于采用全局混入的模式将 vuex 中的数据进行混入,所以我们应该用特定的字符来进行标识 vuex 中的数据,我的建议是在 vuex 中变量前加上特殊前缀 ,或者类似 vuexVar:'xxx' 来进行声明变量。
之后我们就需要在 main.ts 中进行初始化了。
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import installMaxerStore, { Maxer } from './store/maxer.mixin'
...
// 声明全局组件 防止需要this调用时不能识别类型
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$m: Maxer; // 声明全局方法
}
}
...
const app = createApp(App)
installMaxerStore(app)
app.use(store).mount('#app')
之后我们就可以愉快地使用 vuex 了(在注意变量命名的情况下)。
Vuex 数据持久化
这个时候或许你会发现,当页面进行刷新的时候,vuex 的数据会进行初始化(回到最初的状态),这个是由于 vuex 是运行在内存中的,同样的,它的数据也是存储在内存中,当用户进行刷新页面的操作,所以内存数据会重新进行初始化。
那么我们就可以通过 sessionStorage /localStorage/cookie 来进行数据的持久化存储。
页面加载的时候先读取域中的缓存数据,如果有则覆写。当页面将要刷新前,我们将 vuex 的数据存储到域中。
这里建议使用 sessionStorage ,对于需要长时间持久化的数据再使用 localStorage 或者 cookie。
同样我们在 store 目录下新建一个 ts 脚本。
/**
* @作者: WuYunlong
* @时间: 2021/6/22
* @版本: V1.0
* @说明: vuex数据持久化,防止F5之后数据消失
*/
import {Store} from "vuex";
export default<T> (store: Store<T>): void=>{
// 不需要持久化的数据存入sessionStorage
if (sessionStorage.getItem('store')){
store.replaceState(
Object.assign(
{},
store.state,
JSON.parse(sessionStorage.getItem('store') as string)
)
);
// 移除sessionStorage中的数据
sessionStorage.removeItem("store");
}
// 页面刷新的时候进行持久化
window.addEventListener('beforeunload',()=>{
sessionStorage.setItem("store", JSON.stringify(store.state));
})
}
对于需要长时间持久化的数据建议自行定义规则进行封装。
之后我们需要在入口文件中进行声明
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import installMaxerStore, {Maxer} from './store/maxer.mixin'
import initStorePersistence from './store/store.persistence'
...
// 声明全局组件
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$m: Maxer; // 声明全局方法
}
}
...
const app = createApp(App)
installMaxerStore(app) // 全局混入vuex
initStorePersistence(store) // 初始化持久化vuex
app.use(store).mount('#app')
版权说明
本文章转载自网络,如果侵犯了您的权利起联系删除。
网友评论