页面上的Vuex状态刷新


105

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

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

但是刷新页面后,vue应用程序的状态将丢失并重置为默认状态

这会导致出现问题,因为即使用户登录并刷新页面,登录状态也将被设置为false,即使用户保持登录状态,也会显示登录按钮而不是退出按钮。

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

我应该使用Cookie 还是可以使用其他更好的解决方案...

    --

2
我使用任何一种本地存储来处理。这可能是饼干或别的东西
Hammerbot

@El_Matella除了cookie之外,您还可以使用什么方法在本地存储数据
boomboxboy

1
通常,我使用一个本地存储npm软件包,该软件包可以选择最佳方法为我存储数据:npmjs.com/package/local-storage “该API是与所有与localStorage交互的简化方法。请注意,当localStorage为当前浏览器不支持此功能,因此透明地使用了对内存存储的后备支持。”
Hammerbot

@El_Matella非常感谢您……我来看一下
boomboxboy

Answers:


105

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

例如,可以使用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页面...再次谢谢
boomboxboy

8
您需要做一些特定的事情来设置/获取数据吗?重新加载后,我的数据重置为默认值。只需通过this。$ store.state.user进行设置,尝试过的对象和简单的字符串-就没有运气了。
DogCoffee

6
因为cookie是在客户端和服务器之间传输的,所以我可能会改用本地存储...
James Westgate '18年

如何保存aws-amplify的状态?因为它是大,超出了饼干和localStorage的将在Safari上的私人模式不工作
追逐

@hounded我也面临着同样的问题,对此有什么解决方案吗?
阿迪尔

51

创建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();时,用户手动注销。


13
令我感到惊讶的是,Cookie解决方案获得了如此众多的好评。我认为此解决方案更好,因为它会在关闭浏览器窗口时自动清除所有状态。我不喜欢将状态数据作为Cookie发送到服务器,也不想在关闭浏览器窗口时保留敏感数据。
Mark Hagers

标头(包括cookie)的总数也限制为8k。
詹姆斯·韦斯特盖特

2
@MarkHagers,自IE8以来就受到本机支持!无需加载额外的代码。
Fabian von Ellerts

1
我遇到了一个错误 vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
Akin Hwan

1
@Akin-错误表明您在状态中有一个循环引用,一个对象引用另一个对象,该对象最终引用回到第一个对象。
詹姆斯·韦斯特盖特

11

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()]


10

我认为使用Cookies / localStorage保存登录状态在某些情况下可能会导致一些错误。
Firebase已经在localStorage上记录了登录信息,其中包括expirationTime和refreshToken。
因此,我将使用Vue创建的钩子和Firebase api来检查登录状态。
如果令牌已过期,则api将为我们刷新令牌。
因此,我们可以确保在应用程序中显示的登录状态等于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.');
            }
        });
    },
});

针对这种情况的最佳,官方和推荐方法
alijunior

8

置于状态:

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

进行突变:

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

对我来说很好!


1

我已经解决了这个问题,每次重新加载时都会重置标头,以获取用户数据,但我不知道哪个更好。

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

})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.