[英]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.