简体   繁体   English

根据用户是否登录 AWS amplify 有条件地呈现导航栏

[英]conditional render of navbar based on whether user is signed in on AWS amplify

I am attempting to conditionally render a and based on whether or not a user is signed in or not using AWS amplify and Vue 3 for the frontend.我正在尝试根据用户是否登录或不使用 AWS amplify 和 Vue 3 作为前端来有条件地呈现 a and 。 I have been able to get it to not render and then render on sign in but when I log back out the navbar elements are still there and should have disappeared.我已经能够让它不呈现然后在登录时呈现但是当我注销时导航栏元素仍然存在并且应该已经消失。 I am new to Vue, so this maybe an easy fix but am unsure.我是 Vue 的新手,所以这可能是一个简单的修复,但我不确定。 I have tried making using both computed and a watch to try and force update the computed but that is not working.我尝试同时使用计算和手表来尝试强制更新计算但那不起作用。 Any help would be much appreciated.任何帮助将非常感激。 The code is below:代码如下:

<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 } from "aws-amplify";

export default {
  name: "NavBar",
  data() {
    return {
      menuIsOpen: false,
    };
  },
  methods: {
    toggleMenu() {
      this.menuIsOpen = !this.menuIsOpen;
    },
    closeMenu() {
      this.menuIsOpen = false;
    },
    async signOut() {
      try {
        await Auth.signOut();
        // navigate to the login page or another route
        this.$router.push("/");
      } catch (err) {
        console.log(err);
      }
    },
    async isUser() {
      try {
        await Auth.currentAuthenticatedUser();
        return true;
      } catch {
        return false;
      }
    },
  },
  computed: {
    isSignedIn() {
      return this.isUser();
    },
    watch: {
      isSignedIn() {
        this.$forceUpdate();
      },
    },
  },
};
</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>

Update更新

There're way too many "unknowns" in your problem thus it's difficult to give you a working answer.您的问题中有太多“未知数”,因此很难给您一个可行的答案。 I'll give you hints but please read the Vue docs carefully to understand how to implement them and to also better understand the framework.我会给你提示,但请仔细阅读 Vue 文档以了解如何实现它们并更好地理解框架。

As you mentioned in the comments below, you're handling your sign in function in a "sibling" component and that both components are imported in the App.vue .正如您在下面的评论中提到的,您在“同级”组件中处理 function 中的登录,并且这两个组件都导入了App.vue中。

App.vue
views/
... NavBar.vue
... Login.vue

Option #1选项1

Without the use of a state management, what you can do is move this code:如果不使用 state 管理,您可以做的是移动此代码:

export default {
  data() {
    return { isSignedIn: false };
  },
  methods: {
    async isAuthenticated() {
      try {
        await Auth.currentAuthenticatedUser();

        this.isSignedIn = true;
      } catch {
        this.isSignedIn = false;
      }
    },
  }
  async mounted() {
    await this.isAuthenticated();
  }
}

in your App.vue, then use an emitter in the login component so that your App.vue can "listen" whenever the user has logged in successfully.在你的 App.vue 中,然后在登录组件中使用发射器,这样你的 App.vue 就可以在用户成功登录时“监听”。 You can use this.isAuthenticated() as the callback function in the emit event prop.您可以在 emit 事件道具中使用this.isAuthenticated()作为回调 function。 Then, pass the this.isSignedIn state as aprop in your navbar component:然后,将this.isSignedIn state 作为prop传递到导航栏组件中:

Login.vue登录.vue

export default {
  ...
  methods: {
    signInUser() {
      /** your sign in logic */
      this.$emit('signIn')
    }
  }
  ...
}

App.vue App.vue

<!-- Sample template -->
<NavBar :show="isSignedIn" />
<Login @sign-in="isAuthenticated" />

Navbar.vue导航栏.vue

export default {
  props: ['show'] // you can then pass show in your v-show
}

Option #2选项 #2

You can also conditionally render the entire navbar component.您还可以有条件地渲染整个导航栏组件。 However, you need to re-structure your templates a bit:但是,您需要稍微重新构建您的模板:

App.vue App.vue

<Navbar v-show="isSignedIn"/>

Option #3选项 #3

Ideally, App should not be responsible for managing the isSignedIn as the only components that use this state are the NavBar and Login components.理想情况下,App 不应该负责管理isSignedIn ,因为使用此 state 的唯一组件是 NavBar 和 Login 组件。 With that said, consider using Pinia to manage the states between components.话虽如此,考虑使用Pinia来管理组件之间的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AWS Amplify Auth - 获取已登录用户的用户属性时出错 - AWS Amplify Auth - Error when fetching user attributes of a signed in user AWS Amplify UI - 输入确认码后“无法获取登录用户” - AWS Amplify UI - "Failed to get the signed in user" after entering confirmation code 使用 Github 进行基于 AWS Amplify 标签的部署 - AWS Amplify tag based deployment using Github 在 AWS Amplify GraphQL 架构中使用用户信息 - Using user info in AWS Amplify GraphQL schema React 和 AWS Amplify - 根据 Cognito 用户所属的组显示不同的页面 - React and AWS Amplify - Displaying different page based on groups a Cognito user is a member of 在 AWS Amplify 中创建不同的用户类型 - Creating different User Types in AWS Amplify AWS Amplify Google 身份验证用户未重定向回 - AWS Amplify Google auth user not redirected back aws-amplify auth currentSession 不返回当前用户 - aws-amplify auth currentSession returns no current user AWS Amplify:如何在一段时间不活动后使用户 session 过期? - AWS Amplify: How to expire user session after certain time of inactivity? 如何使用 AWS Amplify 和 React 在注册后让用户登录 - How to sign user in after registration using AWS Amplify and React
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM