转载修改自:https://blog.csdn.net/weixin_42505098/article/details/82820174

    在写 Vue.js 时候遇到了一个问题,我在 Index 组件中嵌套了 Login 组件,并且希望在登录成功后,让右侧的「登录」直接变成「用户名」+「注销」。

    一开始也是想着用 sessionStorage 或者 localStorage,但是在 Login 组件中执行 sessionStorage.setItem() 后发现导航里的登录按钮并没有发生改变。刷新后才发生变化,于是就找到了上面的文章,这里记录补充一下。

    这个方法 sessionStorage 和 localStorage 均适用,下面用 sessionStorage 做演示,如果需要可以自己把所有的 sessionStorage 改成 localStorage

    怎么监听

    main.js 中加入:

    Vue.prototype.resetSetItem = function (key, newVal) {
        // 创建一个StorageEvent事件
        var newStorageEvent = document.createEvent('StorageEvent');
        const storage = {
            setItem: function (k, val) {
                sessionStorage.setItem(k, val);
                // 初始化创建的事件
                newStorageEvent.initStorageEvent('setItem', false, false, k, null, val, null, null);
                // 派发对象
                window.dispatchEvent(newStorageEvent)
            }
        }
        return storage.setItem(key, newVal);
    }

    其实原作者这里加了一个 if (key === 'watchStorage') 的判断,当且仅当 key 为 watchStorage 时才执行,我给去掉了因为我觉得没必要,本身这个方法已经限制了你必须使用 this.resetSetItem() 才能触发,如果不需要监听就直接用原来的 setItem() 就行吧我觉得(

    如何触发

    比方说,在我的例子中,我在登录界面输入账号密码,POST 发送给后端然后后端返回了登录成功的结果时,执行 this.resetSetItem(key, value); 代码,例如在 Login.vue 里加入:

    this.$axios.post(后端API, {
        XXX: YYY
    })
    .then(res=> {
        if (判断是否登录成功) {
            sessionStorage.clear();
            this.resetSetItem('login_status',true);
            this.resetSetItem('username',res.data['username']);
            ...
        } else if(登录失败) {
            ...
        }
    })
    .catch(function (error) {
        console.log(error);
    });

    如何监听

    上述例子中,我的登录按钮在 Index.vue 组件里,因此我们可以在 Index.vue 里这么写:

    export default {
        name: Index,
        data() {
            return {
                ...
                login_status: sessionStorage['login_status'],
                username: sessionStorage['username'],
                ...
            };
        },
        created() {
            window.addEventListener('setItem', ()=> {
                this.login_status = sessionStorage.getItem('login_status');
                this.username = sessionStorage.getItem('username');
                this.activeIndex = 1;
            })
        }
    }

    记得给登录和注册按钮套上 v-if:

    <el-menu-item v-if=login_status style=float: right>注销</el-menu-item>
    <el-menu-item v-if=login_status style=float: right>{{username}}</el-menu-item>
    <el-menu-item v-else index=login style=float: right>登录</el-menu-item>

    效果