【问题标题】:Vue: header is not refreshed right away. But localStorage is changedVue:标题不会立即刷新。但是 localStorage 改变了
【发布时间】:2021-03-26 09:49:14
【问题描述】:

当我使用表单登录时:

  1. localStorage 中的 loggedIn 值更改为“true”
  2. 路由器推送到 /home
  3. 标题不变,仍然显示登录/注册按钮

我需要它

  1. localStorage 中的 loggedIn 值更改为“true”
  2. 路由器推送到 /home
  3. 标题更改和图片

Header.vue

      <div class="flex flex-wrap items-center justify-end ">
        <HeaderItem v-if="!isLoggedIn"
            class="pl-10" text = "Login" link="/login"/>
        <HeaderItem v-if="!isLoggedIn" class="pl-10"
                    text = "Signup" link="/signup"/>

        <div v-if="isLoggedIn">
          <UserHeader/>
        </div>
      </div>

export default {
  name: 'App',
  components: {HeaderItem, UserHeader},
  data() {
    return {
      homeLink: "/home"
    }
  },
  created: {
    isLoggedIn() {
      console.log(JSON.parse(localStorage.getItem("loggedIn")) === "true");

      if (localStorage.getItem("loggedIn") === "true")  {
        console.log("STORAGE LOGGED IN TRUE");
      }
      else  {
        console.log("STORAGE LOGGED IN FALSE");
      }

      return localStorage.getItem("loggedIn") === "true";
    }
  }
}

在我按下 Ctrl+Shift+R 后,它只会打印正确的消息并更改标题。但是 localStorage 立即具有正确的 loggedIn 值。我该如何解决?

编辑

我也试过这个:

  <div class="flex flex-wrap items-center justify-end ">
        <HeaderItem v-if="!loggedIn"
            class="pl-10" text = "Login" link="/login"/>
        <HeaderItem v-if="!loggedIn" class="pl-10"
                    text = "Signup" link="/signup"/>

        <div v-if="loggedIn">
          <UserHeader/>
        </div>
      </div>

export default {
  name: 'App',
  components: {HeaderItem, UserHeader},
  data() {
    return {
      homeLink: "/home",
     // loggedIn: false
    }
  },
  computed: {
    loggedIn() {
      return localStorage.getItem("loggedIn") === "true";
    },
...

结果是一样的:只有页面刷新(Ctrl+Shift+R)后header才会改变。

编辑

不能Header 中设置localStorage.loggedIn!在LoginForm.vue中设置,完全不同的组件

【问题讨论】:

  • $("#header").load("../pages/header.html");
  • 不起作用 - 请提供一些诊断检查。控制台.load is not a functionAccess-Control-Allow-Origin 是否有错误。网络标签是否有错误:404 header.html not foundidownvotedbecau.se/itsnotworking
  • 这(很可能)意味着您正在从您的计算机本地打开.html 文件,例如双击您的桌面。以这种方式打开 html 页面时,某些 js 操作(例如 ajax)被阻止给出该消息。您需要从服务器“运行”您的页面 - 例如看到这个问题:stackoverflow.com/questions/5050851/…

标签: javascript vue.js vuejs2


【解决方案1】:

本地存储不是响应式的,因此 VueJS 无法检测到对它的更改。因此,您的计算属性无法跟踪对其的更改

它在重新加载时起作用的原因是计算方法将始终至少运行一次以生成初始值。

您需要将本地存储的更新与布尔值之类的反应变量联系起来。

每次访问本地存储对象时,检查存储值并在 VueJS 中设置一个布尔值 - 类似于 isLoggedIn 并使用它来代替计算方法。

您可以使用 Vuex 和提交,也可以简单地设置头部组件的状态。

例如,创建组件时,您可以根据本地存储密钥是否存在,将 isLoggedIn 设置为 true 或 false。

同样,您也可以在用户登录时将isLoggedIn 设置为 true(与设置本地存储密钥的方法相同),在用户注销时设置为 false。

考虑以下示例:

Header.vue

  <div class="flex flex-wrap items-center justify-end ">
    <HeaderItem v-if="!isLoggedIn"
        class="pl-10" text = "Login" link="/login"/>
    <HeaderItem v-if="!isLoggedIn" class="pl-10"
                text = "Signup" link="/signup"/>

    <div v-if="isLoggedIn">
      <UserHeader/>
    </div>
  </div>

export default {
  name: 'App',
  components: {HeaderItem, UserHeader},
  data() {
    return {
      homeLink: "/home",
      isLoggedIn: false,
    }
  },
  computed: {
      isLoggedIn() {
          return this.$store.state.isLoggedIn;
      }
  },
}

然后在任何其他组件中

  created() {
      if (localStorage.getItem("loggedIn") === "true")  {
          this.$store.commit('SET_LOGGED_IN', true);
      }
  },
  methods: {
       login() {
           localStorage.setItem('loggedIn', 'true');
           this.$store.commit('SET_LOGGED_IN', true); 
       }
  }

对于上面的示例,您有一个 Vuex 存储,其布尔状态称为 isLoggedIn。然后,您提交一个名为 SET_LOGGED_IN 的突变,将 isLoggedIn 的状态设置为 true 或 false。

在任何组件中使用计算属性,您都可以轻松访问isLoggedIn 的值并对其中的更改做出反应性响应。

每次更新或读取本地存储时,还必须更新 VueJS 中的一个变量。该变量是反应性的。

【讨论】:

  • 能否请您展示一些我将如何做到这一点的代码?那个变量会去哪里?我知道如何使用 vuex 的商店,但是页面重新加载后商店被擦除...
  • 正是您使用本地存储存储密钥的原因。让我更新代码给我几分钟时间
  • 我四处询问,每个人都使用 localStorage 作为用户令牌。
  • 你也可以这样做。你需要做的是在你更新本地存储的同时,你也更新你的变量:)
【解决方案2】:

如果您希望您的函数在同一个组件上具有反应性,则创建一个变量并在您设置 localStorage loggedIn 值的位置设置其值。

这只是一个示例代码:

<template>
  <div class="flex flex-wrap items-center justify-end ">
    <h3>{{ isLoggedIn }}</h3>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        loggedIn: false
      }
    },
    created () {
      // added 3 seconds gap to make the value true and check reactivity
      setTimeout(() => this.onSignIn(), 3000)
    },
    computed: {
      
      isLoggedIn() {
        if (localStorage.getItem('loggedIn')) return localStorage.getItem("loggedIn") === "true";
        return this.loggedIn
      }
    },
    methods: {
      onSignIn () {
        this.loggedIn = true
        localStorage.setItem('loggedIn', true)
      }
    }
  }
</script>

更新 2:

previous question 了解您的情况后,与您询问的类似。这是代码,这将在您的情况下为您提供帮助,其中LoginForm.vue 您正在设置 localStorage 值,并且您想在您的App.vue 中使用该值并将其传递给Header.vue。 对于这种情况,我使用Bus Event 来在可能远离父级访问的组件之间进行通信,例如App.vue。

event-bus.js

import Vue from 'vue';
const EventBus = new Vue();
export default EventBus;

LoginForm.vue

<template>
  <div class="home-page">
    <button type="submit" @click="onSignIn()">Login</button>
  </div>
</template>

<script>
import EventBus from '../event-bus';
  export default {
    methods: {
      onSignIn () {
        localStorage.setItem('loggedIn', true)
        EventBus.$emit('OnLogin', true)
      }
    }
  }
</script>

App.vue

<template>
  <div id="app">
    <Header :isLoggedIn="isLoggedIn"/>
    <router-view/>
  </div>
</template>
<script>
import Header from './components/Header'
import EventBus from './event-bus';
export default {
  components: {
    Header
  },
  data() {
    return {
      loggedIn: false
    }
  },
  computed: {
    isLoggedIn() {
      if (localStorage.getItem('loggedIn')) return localStorage.getItem("loggedIn") === "true";
      return this.loggedIn
    }
  },
  created () {
    EventBus.$on('OnLogin', (isLogin) => {
      this.loggedIn = isLogin
    })
  }
}
</script>

Header.vue

<template>
  <div class="flex flex-wrap items-center justify-end ">
    <HeaderItem v-if="!isLoggedIn"
        class="pl-10" text = "Login" link="/login"/>
    <HeaderItem v-if="!isLoggedIn" class="pl-10"
                text = "Signup" link="/signup"/>

    <div v-if="isLoggedIn">
      <UserHeader/>
    </div>
  </div>
</template>

<script>
import HeaderItem from './HeaderItem'
import UserHeader from './UserHeader'
  export default {
    components: {HeaderItem, UserHeader},
    props: ['isLoggedIn']
  }
</script>

【讨论】:

    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2015-12-26
    • 2023-03-30
    • 2023-04-04
    • 2013-12-23
    相关资源
    最近更新 更多