You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于AWS Amplify登录状态的Vue3导航栏条件渲染异常排查

解决Vue3 + AWS Amplify登出后导航栏不更新的问题

问题根源

  1. 计算属性返回Promise而非布尔值:isSignedIn计算属性返回的是异步函数isUser()的Promise对象,Vue无法将Promise直接作为布尔值用于v-show判断,导致初始渲染可能生效,但状态更新时无法响应。
  2. Watch配置位置错误:你把watch写在了computed对象内部,这是无效的,Vue无法识别该监听逻辑。
  3. 未监听Auth状态变化:AWS Amplify的Auth状态变化(比如登出)不会主动通知组件,需要手动监听Auth的状态事件来更新本地状态。

修复步骤

  1. 在data中添加isSignedIn状态变量,存储当前登录状态。
  2. 初始化时调用Auth.currentAuthenticatedUser获取初始登录状态,更新isSignedIn。
  3. 使用Amplify的Hub监听Auth模块的signIn、signOut等事件,实时更新登录状态。
  4. 移除错误的计算属性和无效的watch配置,直接使用data中的isSignedIn做条件渲染。

修改后的完整代码

<template>
  <header>
    <nav class="navbar">
      <router-link @click="closeMenu" to="/" class="nav-branding"
        >Portal</router-link
      >
      <ul :class="[menuIsOpen ? 'active' : '', 'nav-menu']" v-show="isSignedIn">
        <li @click="toggleMenu" class="nav-item">
          <router-link to="/pensions" class="nav-link">Pensions</router-link>
        </li>
        <li @click="toggleMenu" class="nav-item">
          <router-link to="/benefits" class="nav-link">Benefits</router-link>
        </li>
        <li @click="toggleMenu" class="nav-item">
          <router-link to="/annual-leave" class="nav-link"
            >Annual Leave</router-link
          >
        </li>
        <li @click="signOut" class="nav-item">
          <router-link to="/" class="nav-link">Sign Out</router-link>
        </li>
      </ul>
      <div
        @click="toggleMenu"
        :class="[menuIsOpen ? 'active' : '', 'hamburger']"
        v-show="isSignedIn"
      >
        <span class="bar"></span>
        <span class="bar"></span>
        <span class="bar"></span>
      </div>
    </nav>
  </header>
  <div :class="[menuIsOpen ? 'pushed' : 'static']"></div>
</template>

<script>
import { Auth, Hub } from "aws-amplify";

export default {
  name: "NavBar",
  data() {
    return {
      menuIsOpen: false,
      isSignedIn: false
    };
  },
  async mounted() {
    // 初始化获取登录状态
    await this.checkAuthStatus();
    // 监听Auth状态变化
    Hub.listen('auth', (data) => {
      const { payload } = data;
      if (payload.event === 'signIn' || payload.event === 'signOut') {
        this.checkAuthStatus();
      }
    });
  },
  methods: {
    toggleMenu() {
      this.menuIsOpen = !this.menuIsOpen;
    },
    closeMenu() {
      this.menuIsOpen = false;
    },
    async signOut() {
      try {
        await Auth.signOut();
        this.$router.push("/");
      } catch (err) {
        console.log(err);
      }
    },
    async checkAuthStatus() {
      try {
        await Auth.currentAuthenticatedUser();
        this.isSignedIn = true;
      } catch {
        this.isSignedIn = false;
      }
    }
  }
};
</script>

<style>
header {
  height: auto;
  background-color: #0d1520;
}

li {
  list-style: none;
}

a {
  color: white;
  text-decoration: none;
}

.navbar {
  min-height: 70px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
}

.nav-menu {
  display: flex;
  justify-content: space-around;
  align-items: center;
  gap: 60px;
}

.nav-branding {
  font-size: 2rem;
  color: #03e9f4;
}

.nav-branding:hover {
  text-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
    0 0 100px #03e9f4;
}

.nav-link {
  transition: 0.7s ease;
  color: #03e9f4;
}

.nav-link:hover {
  text-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
    0 0 100px #03e9f4;
}

.hamburger {
  display: none;
  cursor: pointer;
}

.bar {
  display: block;
  width: 25px;
  height: 3px;
  margin: 5px auto;
  transition: all 0.3s ease-in-out;
  background-color: #03e9f4;
}

.hamburger:hover .bar {
  box-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
    0 0 100px #03e9f4;
}

@media (max-width: 768px) {
  .static {
    transition: all 0.5s ease-in-out;
    padding-top: 0;
    z-index: 0;
    background-color: #151f31;
  }

  .pushed {
    padding-top: 168px;
    transition: padding 0.3s ease-in-out;
    transition-delay: 0.2;
    z-index: 0;
    background-color: #151f31;
  }
  .hamburger {
    display: block;
  }

  .hamburger.active .bar:nth-child(2) {
    opacity: 0;
  }
  .hamburger.active .bar:nth-child(1) {
    transform: translateY(8px) rotate(45deg);
  }
  .hamburger.active .bar:nth-child(3) {
    transform: translateY(-8px) rotate(-45deg);
  }

  .nav-menu {
    position: fixed;
    left: 100%;
    top: 70px;
    gap: 0;
    flex-direction: column;
    background-color: #0d1520;
    width: 100%;
    text-align: center;
    transition: 0.5s;
  }

  .nav-item {
    margin: 16px 0;
  }

  .nav-menu.active {
    z-index: 1;
    left: 0;
  }
}
</style>

说明

  • 新增checkAuthStatus方法统一处理登录状态检查,更新响应式的isSignedIn变量。
  • 在mounted钩子中初始化状态,并通过Hub.listen监听Auth模块的状态变化,确保登录/登出操作实时同步组件状态。
  • 移除了无效的计算属性和错误放置的watch配置,直接使用isSignedIn变量完成条件渲染。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:30:42