自定义 封装单列模式! global state
由于vue3的响应式系统本身可以脱离组件而存在,因此可以充分利用这一点,轻松制造多个全局响应式数据,
并且通过和vuex一样 通过某个模块指定方法修改数据,不能直接修改数据,并且让数据成为全局响应式
并且在代码体积上绝对的轻量级!比市面上的任何第三方共享数据插件都要轻量。
1.创建一个js ,diy-vuex.js 名字自己定义 我为了模拟共享数据 和vuex相似所以叫这个
2.第二步封装 我们的共享数据模块
diy-vuex.js
// 模拟ajax api接口使用 const userSery = { // 登录接口 login: (name,age) =>{ // 接口返回用户数据 储存在本地 return new Promise((resolve,reject)=>{ setTimeout(()=>{ let user = { name :name, age:age } window.sessionStorage.setItem('user',JSON.stringify(user)) console.log('登录成功') resolve(user) },1000) }) }, // 退出登录 loginOut:()=>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ window.sessionStorage.removeItem('user') resolve('退出成功') },1000) }) }, // 恢复登录 whoAmI:()=>{ // 读取本地储存的用户数据 return new Promise((resolve,reject)=>{ setTimeout(()=>{ let user = window.sessionStorage.getItem('user'); if(user){ user = JSON.parse(user); console.log('恢复成功',user) resolve(user); } else { reject('恢复失败'); }; },1000) }) } } import { reactive,readonly } from 'vue' // 创建默认的全局单列响应式数据,仅供改模块内部使用 const state = reactive({user:null,loading:false}); // 对外保留的数据只能读取,不能修改 // 也可以进一步使用toRefs进行封装,从而避免解构或展开后响应式丢失 export const loginUserStore = readonly(state); // 登录 export async function login (loginId,loginPwd){ state.loading = true const user = await userSery.login(loginId,loginPwd); state.user = user; state.loading = false } // 退出 export async function loginOut (){ state.loading = true await userSery.loginOut(); state.user = null; state.loading = false } // 恢复登录状态 export async function whoAmI (){ state.loading = true try { const user = await userSery.whoAmI(); state.user = user; state.loading = false } catch (e) { state.user = null; } state.loading = false }
3.页面调用我们的封装模块
因为js文件只会加载一次,并且在去读取是有缓存的。
<template> diyVuex<br/> <div> <span >{{loginUserStore.loading?'加载中...':''}}</span> <p v-if="!loginUserStore.user" @click="loginEvent"><span>去登录</span></p> <p v-else-if="loginUserStore.user" @click="loginOutEvent"><span>退出登录</span></p> <div v-if="loginUserStore.user"> <span>用户:{{loginUserStore.user.name}}</span><br/> <span>年龄:{{loginUserStore.user.age}}</span> </div> </div> </template> <script setup> import { login,loginUserStore,loginOut ,whoAmI} from '../store/diy-vuex.js' const router = useRouter(); // 点击 登录 const loginEvent = ()=>{ login('allen',18) }; // 退出登录 const loginOutEvent = ()=>{ loginOut() }; // 恢复登录 whoAmI(); </script> <style scoped> </style>
点击登录 页面最后这样
注意:当我们登录成功了 保存了数据 跳转到其他页面的时候 其他页面需要读取和修改的时候 ,一样的引入这个模块就可以使用了,并且数据是随时更新的,实现了类似vuex的全局响应式共享数据,
也就是说上一个页面修改了 这个模块的state数据,其他任何地方展示或读取到的就是最后一次修改的state数据。
最后优化建议:以上只是一个最基本的结构是这样的,当我们在中大型项目中 全部数据内容和函数写一个文件肯定不行的 建议模块化导入,像vuex一样 一个index.js 其他分模块合并在 一个index.js中