Vuejs2 如何在vue路由器之前运行某些内容

Vuejs2 如何在vue路由器之前运行某些内容,vuejs2,vuex,vue-router,Vuejs2,Vuex,Vue Router,我正在建造我的第一个水疗中心,我面临着一些问题。这就是它的设计方式: Laravel&Laravel视图处理与登录和注册相关的页面 SPA从用户登录页面开始 My app.js定义了一个默认的VueJS应用程序,在该应用程序中,我使用mounted()方法设置登录用户的状态(VUEX)。理想情况下,它所做的只是通过对Laravel后端的axios调用获取用户详细信息,并填充VUEX状态 我在路线定义中使用beforeinter()方法,以确保只有授权人员才能导航到路线 这就是我面临的问题。当用户

我正在建造我的第一个水疗中心,我面临着一些问题。这就是它的设计方式:

  • Laravel&Laravel视图处理与登录和注册相关的页面
  • SPA从用户登录页面开始
  • My app.js定义了一个默认的VueJS应用程序,在该应用程序中,我使用
    mounted()
    方法设置登录用户的状态(VUEX)。理想情况下,它所做的只是通过对Laravel后端的axios调用获取用户详细信息,并填充VUEX状态
  • 我在路线定义中使用
    beforeinter()
    方法,以确保只有授权人员才能导航到路线
  • 这就是我面临的问题。当用户登录时,似乎在设置vuex之前执行了路由器。假设我有一个url/dashboard和/user/1。当我尝试转到user/1时,如果是在加载应用程序之后,它就可以正常工作。但是,如果我在user/1中刷新网页,则router
    beforeEnter
    无法找到用户的vuex状态,因此它会将用户重定向到仪表板。这是因为当路由器在输入之前运行
    时,如果它是一个新的页面加载,它将无法访问用户Vuex状态或它具有访问权限,但该值尚未设置


    由于这个原因,我最大的问题是我不能直接链接到路由页面,因为它总是在仪表板上,然后用户必须转到路由才能工作。我如何处理这种情况?

    我使用$root作为总线,并将VueX作为最后手段,以下是我从正在开发的插件中剥离的一些代码,我对其进行了轻微的修改,以便您只需访问您的代码..,应该可以让您继续使用

    此配置支持VUE Cli

    不要担心会话验证,拦截器将监视来自Laravel的401响应,以提示用户重新验证

    放弃bootstrap.js中的axios配置,并将其替换为此设置和配置访问控制允许源,通配符将适用于本地开发人员

    axios.defaults.withCredentials = true;
    
    axios.defaults.headers.common = {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': undefined,
        'Access-Control-Allow-Origin': '*'
    };
    
    axios.interceptors.response.use(
    
        function (response) {
    
            if(response.headers.hasOwnProperty('x-csrf-token')) {
                axios.defaults.headers['X-CSRF-TOKEN'] = response.headers['x-csrf-token'];
            }
    
            return response;
    
        },
    
        function (error) {
    
            if(typeof error !== 'object' || !error.response) {
                return Promise.reject(error);
            }
    
                if(error.response.hasOwnProperty('status')) {
    
                    switch(error.response.status) {
    
                        case 401:
                        case 419:
                            // DO RE-AUTHENTICATE CALL
                            break;
    
                    }
    
                }
    
            return Promise.reject(error);
    
        }
    
    );
    
    其余的

    在main.js中

    data() {
      return {
        user: {},
        authenticating: false
      }
    },
    
    computed: {
    
        isAuthenticated() {
            // Check a credential only an authorized user would have.
    
            if(this.$router.app.hasOwnProperty('user') === false || this.$router.app.user === null) {
                return false;
            }
    
            return this.$router.app.user.hasOwnProperty('id');
        }
    
    },
    
    methods: {
    
        checkAuth: function () {
    
            this.$set(this.$router.app, 'authenticating', true);
    
            axios.get('/auth/user').then(response => {
    
                this.$set(this.$router.app, 'user', response.data.user);
    
                if (this.$router.app.isAuthenticated()) {
    
                    this.$router.push(this.$router.currentRoute.query.redirect || '/', () => {
                        this.$set(this.$router.app, 'authenticating', false);
                    });
    
                }
    
            }).catch(error => {
    
                // TODO Handle error response
                console.error(error);
                this.$set(this.$router.app, 'user', {});
    
            }).finally(() => {
    
                this.$set(this.$router.app, 'authenticating', false);
    
            });
    
    
        },
    
        login: function (input) {
    
            axios.post('/login', input).then(response => {
    
                this.$set(this.$router.app, 'user', response.data.user);
    
                this.$router.push(this.$router.currentRoute.query.redirect || '/');
    
            }).catch(error => {
                // TODO Handle errors
                console.error(error);
            });
    
        },
    
        logout: function () {
    
            axios.post('/logout').then(response => {
    
                this.$set(this.$router.app, 'user', {});
    
                this.$nextTick(() => {
                    window.location.href = '/';
                });
    
            }).catch(error => {
                console.error(error);
            });
    
        },
    
    }
    
    beforeCreate: function () {
    
        this.$router.beforeResolve((to, from, next) => {
    
            if (to.matched.some(record => record.meta.requiresAuth) && !this.$router.app.isAuthenticated()) {
    
                next({
                    name: 'login',
                    query: {
                        redirect: to.fullPath
                    }
                });
    
                return;
            }
    
            next();
        });
    }
    
    在Auth/LoginController.php中添加方法

    public final function authenticated(Request $request)
    {
        return response()->json([
            'user' => Auth::user()
        ]);
    }
    
    创建app/Http/Middleware/AfterMiddleware.php 它将仅在更改时(而不是每次请求时)传回新的CSRF令牌。当检测到新令牌时,axios拦截器将接收该令牌

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Support\Facades\Cookie;
    
    class AfterMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            if(Cookie::get('X-CSRF-TOKEN',false) !== csrf_token())
                return $next($request)->header('X-CSRF-TOKEN',csrf_token());
    
            return $next($request);
        }
    }
    

    这就是我最后做的。我定义了一个用于初始化Vue的函数

    在app.js的末尾,我使用Axios通过Ajax检索当前用户。在promise的
    then
    方法中,我使用在promise中收到的用户详细信息设置
    存储
    ,然后调用我为上面的Vue初始化定义的函数。这样,当vue初始化时,存储用户已经拥有数据

    代码更改非常小,我不必更改现有的axios实现

    这是我的新实现:

    Axios.get('/api/user/info')
        .then(response => {
            (new Vue).$store.commit('setUser', response.data);
            initializeVue();
        })
        .catch(error => initializeVue());
    
    function initializeVue()
    {
        window.app = new Vue({
            el: '#app',
            router,
            components: {
                UserCard,
                Sidebar,
            },
            methods: mapMutations(['setUser']),
            computed: mapState(['user']),
        });
    }
    

    也许您应该使用本地存储—一个cookie来存储身份验证凭据,然后您可以在beforeEnter方法中访问它。存在一个cookie,其中包含用户详细信息上的加密数据(默认由Laravel创建)。但我不知道如何使用js解密它。而且,我能够在前端使用js对其进行解密,这不是一个安全问题吗?如果可能的话,我真的很想使用其他选项!本地存储可能是可能的,但我希望它在应该的时候使会话过期。本地存储不是用于长期存储吗?在传输过程中,您可以将cookie发送到服务器,对其进行解密并做出相应的响应。谢谢,但我找到了一种更简单的方法。很好,我假设您正在努力实现100%SPA,我使用此设置是因为我使用的是VUE Cli 3而不是laravel mix,生产中的SPA由专用http服务器提供服务,而不是由laravel直接提供服务,因为这样做会出现令牌问题。
    Axios.get('/api/user/info')
        .then(response => {
            (new Vue).$store.commit('setUser', response.data);
            initializeVue();
        })
        .catch(error => initializeVue());
    
    function initializeVue()
    {
        window.app = new Vue({
            el: '#app',
            router,
            components: {
                UserCard,
                Sidebar,
            },
            methods: mapMutations(['setUser']),
            computed: mapState(['user']),
        });
    }