被阻塞的vuejs / vuex应用程序的用户刷新页面如何处理?

时间:2019-06-25 15:35:04

标签: laravel-5 vuejs2

在我的laravel 5.8 / vuejs 2.5 /“ vuex 3.1用户登录到系统中,一些数据存储在用户的存储区中,例如auth / Login.vue:

<script>

    export default {
        ...
        mounted() {
            this.setAppTitle("", 'Login', bus);
        }, // mounted() {

        computed: {
            authError() {
                return this.$store.getters.authError;
            }
        }, // computed: {

        methods: {
            authenticate() {
                this.$store.dispatch('login');    // calling action
                login(this.$data.form)
                    .then((res) => {
                        this.$store.commit("loginSuccess", res);  // calling mutation
                        this.$store.dispatch('retrieveUserLists', res.user.id );
                        this.$router.push({path: '/websites-blogs'}); // For debugging!
                    })
                    .catch((error) => {
                        this.$store.commit("loginFailed", {error});   // calling mutation
                    });
            }
        },  // methods: {

并存储用户帐户及其数据保存在哪里resources / js / store.js:

export default {
    state : {
        currentLoggedUser: user,

        // personal data only for logged user
        userLists: [],
    },

    getters : {
        ...
        userLists(state) {
            return state.userLists;
        },

工作正常,直到登录的用户刷新页面(F5或CTRL + R)并且用户仍登录到我的页面中,但是一些数据(例如(用户列表) 是空的,有些列表是空的。

我有MainApp.vue:

<template>
    <body class="account-body">
    <v-dialog/>

    <MainHeader></MainHeader>
    <div class="content p-0 m-0" style="width: 100% !important; margin: auto !important;">
        <notifications group="wiznext_notification"/>
        <router-view></router-view>
    </div>
    </body>

</template>

<script>

    ...
    export default {
        name: 'main-app',
        components: {MainHeader},

        mixins: [appMixin],

        created() {
        },
        mounted() {
            ...
        },

        methods: {
            ...
        }, // methods: {



    }



</script>

和resources / views / index.blade.php:

<?php $current_dashboard_template = 'Horizontal' ?>

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title id="app_title">{{ config('app.name', 'Laravel') }}</title>

    <link href="{{ asset(('css/Horizontal/bootstrap.min.css')) }}" rel="stylesheet" type="text/css">
    <link href="{{ asset(('css/Horizontal/icons.css')) }}" rel="stylesheet" type="text/css">
    <link href="{{ asset(('css/Horizontal/style.css')) }}" rel="stylesheet" type="text/css">
    ...
    {{--<link href="css/Horizontal/ion.rangeSlider.css" rel="stylesheet" type="text/css"/>--}}
    {{--<link href="css/Horizontal/ion.rangeSlider.skinModern.css" rel="stylesheet" type="text/css"/>--}}
    {{--<link href="css/Horizontal/powerange.css" rel="stylesheet" type="text/css"/>--}}

    <link href="{{ asset(('css/'.$current_dashboard_template.'/app.css')) }}" rel="stylesheet" type="text/css">


    ...

</head>


<body>

<div class="wrapper" id="app">

    <main>
        <div id="main_content">
            <mainapp></mainapp>
        </div>
    </main>

</div>

</body>


@include('footer')
<script src="{{ asset('js/jquery.min.js') }}"></script>
<script src="{{ asset('js/bootstrap.bundle.min.js') }}"></script>

<script src="{{ asset('js/metisMenu.min.js') }}"></script>
<script src="{{ asset('js/waves.min.js') }}"></script>
<script src="{{ asset('js/jquery.slimscroll.min.js') }}"></script>



<script src="{{ asset('js/app.js') }}{{  "?dt=".time()  }}"></script>
{{--<script type="text/javascript" src="{{ asset('js/vuecsv.min.js') }}"></script>--}}

</html>

您能建议这种情况的正确方法吗?我该怎么办?

已修改:

我试图重新制作存储,但看起来还可以:

const user = getLocalUser();

export default {
    state : {
        currentLoggedUser: user,
        isLoggedIn: !!user,
        loading: false,
        auth_error: null,

        api_url: '/api',

        // personal data only for logged user
        userLists: [], // I need to save data on page refresh
    },

    getters : {
        ...
        userLists(state) {

            // that works ok after user logged into the system  and userLists is read on all page without refresh
            if ( state.userLists.length > 0 ) {
                return state.userLists;
            }

            // if userLists is empty check data in localStorage which were saved in refreshUserLists mutation
            let localStorageUserLists = JSON.parse(localStorage.getItem("userLists"));

            if ( localStorageUserLists.length > 0 ) {
                console.log("localStorageUserLists RETURNED::")
                return localStorageUserLists;
            }
            return [];
        },


    },

    mutations : {
        // that works ok after user logged into the system  and his personal data(in my case 5 rows) are read from db into the vuex store
        refreshUserLists(state, payload) {
            state.userLists = payload;
            localStorage.setItem("userLists", JSON.stringify(payload) );
        },


    },

我还要注意什么?

3 个答案:

答案 0 :(得分:2)

问题是,Vuex控制着整个应用程序和组件的数据状态,但是一旦用户按下F5或任何其他刷新选项,Vuex就会重置,您无能为力,就像它一样有效。

我现在可以想到的一种解决方案是将数据保存在Vuex上,也许还保存在localstorage上,然后在vuex创建生命周期中,如果数据为空,则可以用localstorage数据填充数据。

答案 1 :(得分:1)

我不同意提议的解决方案。浏览器刷新通常表示用户希望从服务器获取最新鲜的数据,并使用该新鲜数据重置应用程序状态。因此,您不应将Vuex状态存储在localStorage或cookie中来解决此问题。如果这样做的话,您现在可以将应用程序状态放在两个位置,并且用户认为不使用时,它们会拥有最新鲜的数据。

在SPA中处理浏览器刷新事件的最佳方法是从头开始引导状态。刷新后加载您的应用程序时,它应注意用户未登录(因为这是默认状态),并且应通过与幕后服务器进行协商(例如,发送会话cookie和接收)来登录用户。确认(如果会话已过期,则重定向到登录页面)。它还应该从服务器重新获取所有相关数据,然后再次将其存储在Vuex中。

答案 2 :(得分:0)

您可以同时使用localStorage和cookie。由于我在LocalStorage中遇到的问题,我建议使用cookie。 Vue有一个名为Vue-cookies的丰富插件。

您可以通过以下命令设置和获取数据:

var user = { id:1, name:'Journal',session:'25j_7Sl6xDq2Kc3ym0fmrSSk2xV2XkUkX' }; this.$cookies.set('user',user); // print user name console.log(this.$cookies.get('user').name)

更多详细信息: Github