【问题标题】:Vuex state on page refresh页面刷新时的 Vuex 状态
【发布时间】:2017-08-19 01:04:13
【问题描述】:

我的应用使用 Firebase API 进行用户身份验证,将登录状态保存为 Vuex 状态中的布尔值。

当用户登录时,我设置登录状态并相应地有条件地显示登录/注销按钮。

但是当页面刷新时,vue app的状态丢失并重置为默认

这会导致一个问题,因为即使用户登录并刷新页面,登录状态 设置回 false 并且显示登录按钮而不是注销按钮,即使用户保持登录状态....

我应该怎么做才能防止这种行为

我应该使用 cookies 或者有任何其他更好的解决方案可用...

    -

【问题讨论】:

  • 我使用任何类型的本地存储来处理它。那可以是 Cookie 或其他东西
  • @El_Matella 除了 cookie 你还用什么方法在本地存储数据
  • 一般来说,我使用本地存储的npm包,它可以为我选择最好的存储数据的方法:npmjs.com/package/local-storage"API是与localStorage所有东西交互的一种简化方式。注意当当前浏览器不支持 localStorage,回退到内存存储是透明的。”
  • @El_Matella 非常感谢...我去看看

标签: javascript vue.js vuejs2 state vuex


【解决方案1】:

这是一个已知的用例。有不同的解决方案。

例如,可以使用vuex-persistedstate。这是vuex 的插件,用于处理和存储页面刷新之间的状态。

示例代码:

import { Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

const store = new Store({
  // ...
  plugins: [
    createPersistedState({
      getState: (key) => Cookies.getJSON(key),
      setState: (key, state) => Cookies.set(key, state, { expires: 3, secure: true })
    })
  ]
})

我们在这里做的很简单:

  1. 需要安装js-cookie
  2. getState 上,我们尝试从Cookies 加载保存的状态
  3. setState 上,我们将状态保存到Cookies

文档和安装说明:https://www.npmjs.com/package/vuex-persistedstate

【讨论】:

  • 谢谢...刚刚看了插件的github页面...再次感谢
  • 您需要做任何特定的事情来设置/获取数据吗?重新加载时,我的数据被重置为默认值。只是通过 this.$store.state.user 设置,尝试过的对象和简单的字符串 - 没有运气。
  • 因为 cookie 在客户端和服务器之间传输,所以我可能会查看本地存储...
  • 如何保存 aws-amplify 的状态?因为它太大了,无法放入 cookie 中,并且 localstorage 无法在 safari 私有模式下运行
  • @hounded 我也面临同样的问题,找到解决办法了吗?
【解决方案2】:

创建 VueX 状态时,使用 vuex-persistedstate 插件将其保存到会话存储中。这样,当浏览器关闭时,信息就会丢失。避免使用 cookie,因为这些值会在客户端和服务器之间传输。

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex);

export default new Vuex.Store({
    plugins: [createPersistedState({
        storage: window.sessionStorage,
    })],
    state: {
        //....
    }
});

当用户手动注销时使用sessionStorage.clear();

编辑:请注意,如果您的商店有本质上不是字符串类型的值(例如日期),您的应用程序可能会失败或行为可能会改变,因为序列化/反序列化过程会将这些值转换为字符串。

【讨论】:

  • 我很惊讶 cookie 解决方案获得了如此多的星星。我认为这个解决方案要好得多,因为它会在浏览器窗口关闭时自动清除所有状态。我不喜欢将我的状态数据作为 cookie 发送到服务器,我也不想在浏览器窗口关闭时保留敏感数据。
  • 包含 cookie 在内的标头总数也被限制为 8k。
  • @MarkHagers 并且从 IE8 开始原生支持!无需加载额外的代码。
  • 我收到一个错误vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
  • @Akin - 该错误表明您的状态中有一个循环引用,一个对象引用了另一个对象,该对象最终引用回第一个对象。
【解决方案3】:

Vuex 状态保存在内存中。页面加载将清除此当前状态。这就是状态在重新加载时不会持续存在的原因。

但是vuex-persistedstate 插件解决了这个问题

npm install --save vuex-persistedstate

现在将其导入商店。

import Vue from 'vue'
import Vuex from 'vuex'
import account from './modules/account'
import createPersistedState from "vuex-persistedstate";

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    account,
  },
  plugins: [createPersistedState()]
});

只需一行代码即可完美运行:plugins: [createPersistedState()]

【讨论】:

  • with vuex create store: const store = createStore({ /*...*/ plugins: [createPersistedState()], });
  • 这是最简单的方法,无需添加其他包。它有效!
【解决方案4】:

我认为使用 cookie/localStorage 保存登录状态在某些情况下可能会导致一些错误。
Firebase 已经为我们在 localStorage 记录了登录信息,包括 expireTime 和 refreshToken。
因此,我将使用 Vue 创建的钩子和 Firebase api 来检查登录状态。
如果token过期了,api会为我们刷新token。
所以我们可以确保在我们的应用中显示的登录状态与 Firebase 相同。

new Vue({
    el: '#app',
    created() {
        firebase.auth().onAuthStateChanged((user) => {
            if (user) {
                log('User is logined');
                // update data or vuex state
            } else {
                log('User is not logged in.');
            }
        });
    },
});

【讨论】:

  • 针对这种情况的最佳、官方和推荐方法
【解决方案5】:

进入状态:

producer: JSON.parse(localStorage.getItem('producer') || "{}")

进行突变:

localStorage.setItem("producer",JSON.stringify(state.producer)) // OR
localStorage.removeItem("producers");

对我来说很好用!

【讨论】:

    【解决方案6】:

    我已经通过每次重新加载时重置我的标题来解决这个问题,还获取用户数据,我不知道什么更好......

    new Vue({
        el: 'vue',
        render: h => h(VueBox),
        router,
        store,
    
        computed: {
            tokenJWT () {
                return this.$store.getters.tokenCheck
            },
        },
    
    
        created() {
            this.setAuth()
    
        },
    
        methods:
            Object.assign({}, mapActions(['setUser']), {
    
                setAuth(){
                    if (this.tokenJWT) {
                        if (this.tokenJWT === 'expired') {
                            this.$store.dispatch('destroyAuth')
                            this.$store.dispatch('openModal')
                            this.$store.dispatch('setElModal', 'form-login')
    
                        } else {
                            window.axios.defaults.headers.common = {
                                'Accept': 'application/json',
                                'Authorization': 'Bearer ' + this.tokenJWT
                            }
                            axios.get( api.domain + api.authApi )
                                .then(res => {
                                    if (res.status == 200) {
                                        this.setUser( res.data.user )
                                    }
                                })
                                .catch( errors => {
                                    console.log(errors)
                                    this.destroyAuth()
                                })
                        }
                    }
                }
            })
    
    })
    

    【讨论】:

      【解决方案7】:

      在这种情况下,最简单的方法是安装 npm install --save vuex-persistedstate
      然后,将其导入您的 vuex 文件 从“vuex-persistedstate”导入 createPersistedState;然后,只需将其放入您的 createStore 中,如下所示:

      plugins: [createPersistedState()],
          state(){
              return{
                  isActive: false,
              }
          }
      

      【讨论】:

        【解决方案8】:

        这里是如何使用组合 api 来做到这一点。

        npm install --save vuex-persistedstate

        import createPersistedState from "vuex-persistedstate";
        import { createStore } from "vuex";
        
        export default createStore({
          state: {
            project_id: 1,
          },
          mutations: {
            setProjectId(state, payload) {
              state.project_id = payload;
            },
          },
          getters: {},
          actions: {},
          plugins: [createPersistedState()],
        });
        

        【讨论】:

          猜你喜欢
          • 2020-03-11
          • 2021-03-20
          • 1970-01-01
          • 2017-08-22
          • 2018-09-17
          • 2020-08-14
          • 1970-01-01
          • 2021-11-14
          • 2019-11-23
          相关资源
          最近更新 更多