简体   繁体   English

页面刷新时的 Vuex 状态

[英]Vuex state on page refresh

My app uses the Firebase API for User Authentication, saving the Login status as a boolean value in a Vuex State.我的应用程序使用 Firebase API 进行用户身份验证,将登录状态保存为 Vuex 状态中的布尔值。

When the user logs in I set the login status and conditionally display the Login/Logout button accordingly.当用户登录时,我设置登录状态并相应地有条件地显示登录/注销按钮。

But when the​ page is refreshed, the state of the vue app is lost and reset to default但是当页面刷新时,vue app的状态丢失并重置为默认

This causes a problem as even when the user is logged in and the page is refreshed the login status is set back to false and the login button is displayed instead of logout button even though the user stays logged in....这会导致问题,因为即使用户登录并刷新页面,登录状态也会设置回false并且即使用户保持登录状态,也会显示登录按钮而不是注销按钮......

What shall I do to prevent this behavior我该怎么做才能防止这种行为

Shall I use cookies Or any other better solution is available...我应该使用cookie还是可以使用任何其他更好的解决方案...

    - -

This is a known use case.这是一个已知的用例。 There are different solutions.有不同的解决方案。

For example, one can use vuex-persistedstate .例如,可以使用vuex-persistedstate This is a plugin for vuex to handle and store state between page refreshes.这是vuex处理和存储页面刷新之间状态的插件。

Sample code:示例代码:

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

What we do here is simple:我们在这里做的很简单:

  1. you need to install js-cookie你需要安装js-cookie
  2. on getState we try to load saved state from CookiesgetState上,我们尝试从Cookies中加载保存的状态
  3. on setState we save our state to CookiessetState上,我们将状态保存到Cookies

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

When creating your VueX state, save it to session storage using the vuex-persistedstate plugin.创建 VueX 状态时,使用vuex-persistedstate插件将其保存到会话存储中。 In this way, the information will be lost when the browser is closed.这样,当浏览器关闭时,信息就会丢失。 Avoid use of cookies as these values will travel between client and server.避免使用 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: {
        //....
    }
});

Use sessionStorage.clear();使用sessionStorage.clear(); when user logs out manually.当用户手动注销时。

EDIT: Note that if your store have values that are not intrinsically string types (eg dates), your application may fail or behaviour may change because the serialisation/deserialisation process will convert these values to strings.编辑:请注意,如果您的商店具有本质上不是字符串类型的值(例如日期),您的应用程序可能会失败或行为可能会改变,因为序列化/反序列化过程会将这些值转换为字符串。

Vuex state is kept in memory. Vuex 状态保存在内存中。 Page load will purge this current state.页面加载将清除此当前状态。 This is why the state does not persist on reload.这就是为什么状态不会在重新加载时持续存在的原因。

But the vuex-persistedstate plugin solves this issue但是vuex-persistedstate插件解决了这个问题

npm install --save vuex-persistedstate

Now import this into the store.现在将其导入商店。

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

It worked perfectly with a single line of code: plugins: [createPersistedState()]它与一行代码完美配合: plugins: [createPersistedState()]

put on state:装上状态:

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

put on mutations:进行突变:

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

works fine for me!对我来说很好!

I think use cookies/localStorage to save login status might cause some error in some situation.我认为在某些情况下使用 cookies/localStorage 保存登录状态可能会导致一些错误。
Firebase already record login information at localStorage for us include expirationTime and refreshToken. Firebase 已经为我们在 localStorage 记录了登录信息,包括 expireTime 和 refreshToken。
Therefore I will use Vue created hook and Firebase api to check login status.因此,我将使用 Vue 创建的钩子和 Firebase api 来检查登录状态。
If token was expired, the api will refresh token for us.如果token过期了,api会为我们刷新token。
So we can make sure the login status display in our app is equal to Firebase.所以我们可以确保我们的应用程序中的登录状态显示等于 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.');
            }
        });
    },
});

I've solved this by resetting my headers every time I re-load also fetch user data, I don't know what is better ...我已经通过每次重新加载时重置我的标题来解决这个问题,还获取用户数据,我不知道什么更好......

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

})

Here's how to do it with the composition api.以下是使用组合 API 的方法。

npm install --save vuex-persistedstate 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()],
});

In this case, the easiest way is installing npm install --save vuex-persistedstate在这种情况下,最简单的方法是安装 npm install --save vuex-persistedstate
Then, Importing it into your vuex file import createPersistedState from "vuex-persistedstate";然后,将其导入您的 vuex 文件 import createPersistedState from "vuex-persistedstate"; Then, just put it in your createStore like:然后,只需将其放入您的 createStore 中,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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