В VueJS версии 3, каков правильный способ показать и скрыть ссылки входа и выхода <router-link> и наоборот, которые размещены на панели навигации?

avatar
Karthik S A
1 июля 2021 в 16:07
1271
1
0

Я новичок в VueJS. Я разработал простой экран входа в систему. После успешного входа сервер отправит идентификатор пользователя в формате JSON. Я сохраняю этот идентификатор пользователя в localStorage. Используя это, я подумал о том, чтобы показать логин (до входа в систему). После входа в систему, 1. должен отображаться выход из системы, а не вход и 2. компонент входа должен отображаться при выходе из системы, нажмите

В текущем коде ссылка "Пост-логин" и "Выход" не отображается. Я также попробовал логику v-else. Это тоже не сработало. ссылка https://forum.vuejs.org/t/update-navbar-login-logout-button/103509

Сообщите мне, какая ошибка в приведенном ниже коде. Заранее спасибо.

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>

Логин.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')

Ссылка на изображение изменений, предложенных Keenal.

https://drive.google.com/file/d/1_EOJTM2HhJnAYjBJCaSobA2i2LS-cOww/view?usp=sharing

Источник

Ответы (1)

avatar
developer
2 июля 2021 в 07:58
0

LocalStorage не является реактивным, vuejs может обнаруживать изменения в свойствах, которые были созданы в экземпляре. Таким образом, он будет обнаружен только после рефереша страницы. Следующий код будет работать

    <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();
   }
  }
});

Вы можете обновить значение в соответствии с вашими требованиями.

Karthik S A
2 июля 2021 в 14:00
0

Привет @Keenal, я использовал эту логику. Но перед входом в систему на панели навигации отображается кнопка «Выход». Не могли бы вы отредактировать точную логику в файле JS, которую я упомянул в описании? Спасибо

Karthik S A
2 июля 2021 в 14:05
0

Я попробовал логику шины событий, чтобы реализовать это. Но панель навигации исчезла, когда я добавил код в раздел data(). Дайте мне знать, если это выглядит осуществимым? laracasts.com/discuss/channels/vue/…

developer
4 июля 2021 в 03:44
0

Выход отображается, потому что этот ключ может храниться в локальном хранилище. Сначала удалите этот ключ из хранилища, а затем попробуйте.

Karthik S A
5 июля 2021 в 04:59
0

Привет @Keenal, я удалил локальное хранилище и попробовал. Но по-прежнему отображается только кнопка «Выход». Прикрепите изображение к описанию вопроса.

Karthik S A
5 июля 2021 в 05:48
0

Привет @Keenal, я приложил ссылку на изображение к описанию. Пожалуйста, посмотрите. Дайте мне знать ваше предложение.

developer
6 июля 2021 в 10:28
0

Пожалуйста, добавьте здесь ссылку на скрипку. Тогда мы сможем проследить это.