简体   繁体   中英

Reactive nav component in Vue

I'm trying to create a simple reactive navigation based on if a user is authenticated or not. A login method on a login view sets a token in localstorage. If set, I want to display the logout button. I've tried computed, standard methods and props to no avail.

When I login, the navigation does not update. HOWEVER, if I refresh the page (reinitialize the app), it does show the logout button.

What exactly am I doing incorrectly?

I have been trying for hours to grasp the concept of Vue JS and am on the brink of quitting. What would have taken me minutes to do server side has taken me hours client side. WHERE IS THE REACTIVITY?

Nav.vue

  <template>
    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
      <a class="navbar-brand" href="#">App</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarColor01">
        <ul class="navbar-nav">
          <li class="nav-item active">
            <a class="nav-link" href="#">
              <router-link to="/">Home</router-link>
              <span class="sr-only">(current)</span>
            </a>
          </li>
          <li class="nav-item">
              <router-link to="/about" class="nav-link">About</router-link>
          </li>
        </ul>
        <ul class="navbar-nav ml-auto">
          <li class="nav-item" v-if="hasAuth()"><a @click="logout()" class="nav-link">Log Out</a></li>
          <template v-else> 
            <li class="nav-item">
              <router-link to="/register" class="nav-link">Register</router-link>
            </li>
            <li class="nav-item">
              <router-link to="/login" class="nav-link">Login</router-link>
            </li>
          </template>
        </ul>
      </div>
    </nav>
  </template>

  <script>
  export default {
    name: 'Nav',
    data: () => {
      return {
        auth: false
      }
    },
    methods: {
      logout: function () {
        localStorage.removeItem('user-token');
        this.$router.push({ path: 'login' });
      },
      hasAuth: function () {
        this.auth = (localStorage.getItem('user-token')) ? true : false;
        return this.auth
      }
    },
  };
  </script>

App.vue

<template>
  <div id="app">
    <Nav></Nav>
    <router-view/>
  </div>
</template>

<script>
import Nav from '@/components/Nav.vue';

export default {
  components: {
    Nav,
  },
}
</script>

While Vue.js is reactive, localStorage is not. Vue cannot possibly know if the localStorage is modified or not. There is no local change event available with local storage.

To solve this problem, use Vuex combined with Local Storage for persistent data. The point where you save the token to local storage, at that time also save a copy inside Vuex store.

Another component like Nav should read data from Vuex store which is reactive. When you refresh the page, initialize Vuex store with the data from localStorage .

This way you get a perfect reactive system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM