- 首页
- 前端开发
- 在 VueJS 版本 3 中,显示和隐藏登录的正确方法是什么?注销<路由器链接>链接,反之亦然,哪个放置在导航栏上?
在 VueJS 版本 3 中,显示和隐藏登录的正确方法是什么?注销<路由器链接>链接,反之亦然,哪个放置在导航栏上?
[英] In VueJS version 3, What is the correct way to Show and Hide the Login & Logout <router-link> links and viceversa which is placed on Nav Bar?
本文介绍了在 VueJS 版本 3 中,显示和隐藏登录的正确方法是什么?注销<路由器链接>链接,反之亦然,哪个放置在导航栏上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我是 VueJS 的新手.我开发了一个简单的登录屏幕.登录成功后,Server 会以 JSON 格式发送 userId.我将此用户 ID 存储在 localStorage 中.使用这个,我想到了显示登录(登录前).登录后,1. 应显示注销,而不是登录和登录.2.登录组件应在注销时显示
在当前代码中,登录后、注销链接不可见.我也尝试过 v-else 逻辑.这也没有奏效.参考 https://forum.vuejs.org/t/update-navbar-login-logout-button/103509
让我知道下面的代码有什么错误.提前致谢.
App.vue
<div id="应用程序"><导航/><路由器视图/>
</模板><脚本>从'./components/Nav.vue'导入导航导出默认{name: '应用程序',成分: {导航},数据() {返回 {形式: {用户名:'',密码:''},显示错误:假};},};<风格>@import url('htpp://fonts.googleapis.com/css?family=Fira+Sans:400,500,600,700,800');* {box-sizing:border-box;}身体{背景:#fcfdfd !重要;}正文,html,#app,#root,.auth-wrapper{宽度:100%;高度:100%;填充顶部:30px;}#应用程序{文字对齐:居中;}.navbar-light{背景色:#167bff;box-shadow:0px 14px 80px rgba (34,35,58,0.2);}.custom-control-label{字体粗细:100;}.forgot-password, .forgot-password a{文本对齐:右;字体大小:13px;填充顶部:10px;颜色:#7f7d7d;保证金:0;}.forgot-password a{颜色:#167bff;}</风格>
导航.vue
<nav class="navbar navbar-expand navbar-light fixed-top"><div class="container"><router-link to="/";class =导航栏品牌">测试数据生成器</router-link><div class="collapse navbar-collapse"><ul class="navbar-nav ml-auto"><li class="nav-item";v-if="isLoggedIn==null"><router-link to="/login";class =导航链接">登录</router-link><li class="nav-item";v-else ><router-link @click="handleLogout";class =导航链接">注销</router-link>
</nav></模板><脚本>导出默认{name:'导航',计算:{isLoggedIn() {返回 window.localStorage.getItem("userId");}},方法:{句柄注销(){localStorage.removeItem('userId');this.$router.push('/登录');}}}<风格>nav .navbar-nav li a{颜色:白色!重要;}</风格>
登录.vue
<div class="auth-wrapper"><div class="auth-inner"><h4>登录</h4><p><label>用户名</label><输入类型=文本"v-model="state.username";占位符=用户名"class =表单控件"/></p><p><label>密码</label><输入类型=密码"类=表单控制"v-model=state.password"占位符=密码"/></p><button @click="handleLogin";class=btn btn-primary btn-block">登录</button>
</模板><脚本>从@vuelidate/validators"导入{必需}从@vuelidate/core"导入 useValidate从 'axios' 导入 axios从 '../config' 导入 { apiHost }从 'vue' 导入 {reactive, 计算}导出默认{name:'登录',设置() {const 状态 = 反应性({用户名:'',密码:'',})const 规则=计算(()=> {返回 {用户名:{必填},需要密码 },}})const v$ = useValidate(rules,state)返回{状态,v$,}},方法:{异步 handleLogin(){this.v$.$validate()如果 (!this.v$.$error) {const loginURL=apiHost+'认证';const response = await axios.post(loginURL,{用户名:this.state.username,密码:this.state.password});控制台日志(响应);localStorage.setItem('userId',response.data.userId);this.$router.push('/hello');}别的{alert('请输入用户名和密码.')}}}}<风格>.auth-包装器{显示:弹性;对齐内容:中心;弹性方向:列;文本对齐:左;}.auth-内{宽度:300px;保证金:自动;背景:#167bff;box-shadow:0px 14px 80px rgba (34,35,58,0.2);填充:40px 55px 45px 55px;边框半径:15px;过渡:所有 .3s;}.auth-wrapper .form-control:focus{边框颜色:#167bff;框阴影:无;}.auth-wrapper h4{文字对齐:居中;保证金:0;行高:1;填充底部:20px;}</风格>
main.js
import { createApp } from 'vue'import { createRouter, createWebHistory } from 'vue-router'从'./App.vue'导入应用程序从'./components/Login.vue'导入登录从 './components/Home.vue' 导入 Home从'./components/States.vue'导入状态从 './components/HelloWorld.vue' 导入 HelloWorld从@meforma/vue-toaster"导入烤面包机;const 路由器 = createRouter({历史记录:createWebHistory(),路线:[{路径:'/登录',组件:登录},{路径:'/getStates',组件:状态},{小路 : '/',组件:首页},{路径:'/你好',组件:HelloWorld},]})const app= createApp(App);app.use(router).use(Toaster).mount('#app')
Keenal 建议更改的图片链接.
https://drive.google.com/file/d/1_EOJTM2HhJnAYjBJCaSobA2i2LS-cOww/view?usp=sharing
解决方案
LocalStorage 不是响应式的,vuejs 可以检测在实例中创建的属性的变化.所以只有在页面引用后才会被检测到.以下代码将起作用
<button @click="setLogin">{{loggedIn !== 'null' ?'注销' : '登录'}} </button>
JS
new Vue({el: '#app',数据:函数(){返回 {获取登录(){返回 localStorage.getItem('userId');},设置登录(值){localStorage.setItem('userId', value);}};},方法:{设置登录(){if(localStorage.getItem('userId') !=='null')this.userId = null;别的this.userId = Math.random();}}});
您可以根据需要更新该值.
I am newbie to VueJS. I have developed a simple Login Screen. After successful Login, Server will send userId in JSON format. I am storing this userId in localStorage. Using this, I thought of showing the Login (before Login). Post Login, 1. the Logout should be displayed and not Login & 2. Login Component should be displayed on logout click
In current code, Post Login, Logout link is not visible. I also tried v-else logic. That also did not worked. referce https://forum.vuejs.org/t/update-navbar-login-logout-button/103509
Let me know what mistake is there in the below code. Thanks in advance.
App.vue
<template>
<div id="app">
<Nav/>
<router-view />
</div>
</template>
<script>
import Nav from './components/Nav.vue'
export default {
name: 'App',
components: {
Nav
},
data() {
return {
form: {
username:'',
password:''
},
showError: false
};
},
};
</script>
<style>
@import url('htpp://fonts.googleapis.com/css?family=Fira+Sans:400,500,600,700,800');
* {
box-sizing:border-box;
}
body{
background: #fcfdfd !important;
}
body, html,#app, #root, .auth-wrapper{
width :100%;
height:100%;
padding-top:30px;
}
#app{
text-align:center;
}
.navbar-light{
background-color: #167bff;
box-shadow:0px 14px 80px rgba (34,35,58,0.2);
}
.custom-control-label{
font-weight:100;
}
.forgot-password, .forgot-password a{
text-align : right;
font-size : 13px;
padding-top:10px;
color:#7f7d7d;
margin:0;
}
.forgot-password a{
color:#167bff;
}
</style>
Nav.vue
<template>
<nav class="navbar navbar-expand navbar-light fixed-top">
<div class="container">
<router-link to="/" class="navbar-brand" > Test Data Generator </router-link>
<div class="collapse navbar-collapse">
<ul class="navbar-nav ml-auto">
<li class="nav-item" v-if="isLoggedIn==null">
<router-link to="/login" class="nav-link"> Login </router-link>
</li>
<li class="nav-item" v-else >
<router-link @click="handleLogout" class="nav-link"> Logout </router-link>
</li>
</ul>
</div>
</div>
</nav>
</template>
<script>
export default {
name:'Nav',
computed: {
isLoggedIn() {
return window.localStorage.getItem("userId");
}
},
methods:{
handleLogout(){
localStorage.removeItem('userId');
this.$router.push('/login');
}
}
}
</script>
<style>
nav .navbar-nav li a{
color: white !important;
}
</style>
Login.vue
<template>
<div class="auth-wrapper">
<div class="auth-inner">
<h4>Login</h4>
<p>
<label>Username</label>
<input type="text" v-model="state.username" placeholder="Username" class="form-control"/>
</p>
<p>
<label>Password</label>
<input type="password" class="form-control" v-model="state.password" placeholder="Password"/>
</p>
<button @click="handleLogin" class="btn btn-primary btn-block">Login</button>
</div>
</div>
</template>
<script>
import { required } from '@vuelidate/validators'
import useValidate from '@vuelidate/core'
import axios from 'axios'
import { apiHost } from '../config'
import {reactive, computed} from 'vue'
export default {
name:'Login',
setup() {
const state = reactive({
username:'',
password:'',
})
const rules=computed(() => {
return {
username: { required },
password: { required },
}
})
const v$ = useValidate(rules,state)
return{
state,v$,
}
},
methods:{
async handleLogin(){
this.v$.$validate()
if (!this.v$.$error) {
const loginURL=apiHost+'authenticate';
const response = await axios.post(loginURL,{
username:this.state.username,
password: this.state.password
});
console.log(response);
localStorage.setItem('userId',response.data.userId);
this.$router.push('/hello');
}else{
alert('Please enter username and password.')
}
}
}
}
</script>
<style>
.auth-wrapper{
display:flex;
justify-content:center;
flex-direction:column;
text-align:left;
}
.auth-inner{
width:300px;
margin :auto;
background: #167bff;
box-shadow:0px 14px 80px rgba (34,35,58,0.2);
padding:40px 55px 45px 55px;
border-radius:15px;
transition: all .3s;
}
.auth-wrapper .form-control:focus{
border-color:#167bff;
box-shadow:none;
}
.auth-wrapper h4{
text-align:center;
margin:0;
line-height:1;
padding-bottom:20px;
}
</style>
main.js
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Login from './components/Login.vue'
import Home from './components/Home.vue'
import States from './components/States.vue'
import HelloWorld from './components/HelloWorld.vue'
import Toaster from '@meforma/vue-toaster';
const router = createRouter({
history: createWebHistory(),
routes:[
{
path : '/login',
component:Login
},
{
path : '/getStates',
component:States
},
{
path : '/',
component:Home
},
{
path : '/hello',
component:HelloWorld
},
]
})
const app= createApp(App);
app.use(router).use(Toaster).mount('#app')
Image Link for the changes suggested by Keenal.
https://drive.google.com/file/d/1_EOJTM2HhJnAYjBJCaSobA2i2LS-cOww/view?usp=sharing
解决方案
LocalStorage is not reactive, vuejs can detect changes in properties which were created in the instance. So it will be detected only after page referesh.
Following code will work
<div id="app">
<button @click="setLogin"> {{loggedIn !== 'null' ? 'Logout' : 'Login'}} </button>
</div>
JS
new Vue({
el: '#app',
data: function() {
return {
get loggedIn() {
return localStorage.getItem('userId');
},
set loggedIn(value) {
localStorage.setItem('userId', value);
}
};
},
methods:{
setLogin(){
if(localStorage.getItem('userId') !== 'null')
this.userId = null;
else
this.userId = Math.random();
}
}
});
You can update the value according to your requirement.
这篇关于在 VueJS 版本 3 中,显示和隐藏登录的正确方法是什么?注销<路由器链接>链接,反之亦然,哪个放置在导航栏上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!