发布时间:2022-11-24 文章分类:编程知识 投稿人:王小丽 字号: 默认 | | 超大 打印

自定义 封装单列模式! global state

由于vue3的响应式系统本身可以脱离组件而存在,因此可以充分利用这一点,轻松制造多个全局响应式数据,
并且通过和vuex一样 通过某个模块指定方法修改数据,不能直接修改数据,并且让数据成为全局响应式
并且在代码体积上绝对的轻量级!比市面上的任何第三方共享数据插件都要轻量。

1.创建一个js ,diy-vuex.js 名字自己定义 我为了模拟共享数据 和vuex相似所以叫这个

VUE3 全局共享数据方案之一 global state (简单快速实现类似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>

点击登录 页面最后这样

VUE3 全局共享数据方案之一 global state (简单快速实现类似vuex)

注意:当我们登录成功了 保存了数据 跳转到其他页面的时候 其他页面需要读取和修改的时候 ,一样的引入这个模块就可以使用了,并且数据是随时更新的,实现了类似vuex的全局响应式共享数据,

也就是说上一个页面修改了 这个模块的state数据,其他任何地方展示或读取到的就是最后一次修改的state数据。

最后优化建议:以上只是一个最基本的结构是这样的,当我们在中大型项目中 全部数据内容和函数写一个文件肯定不行的 建议模块化导入,像vuex一样 一个index.js 其他分模块合并在 一个index.js中