programing

vue-router보다 먼저 무언가를 실행하는 방법

bestcode 2022. 8. 16. 23:22
반응형

vue-router보다 먼저 무언가를 실행하는 방법

첫 번째 SPA를 만들고 있는데 몇 가지 문제가 있어요.설계 방법은 다음과 같습니다.

  1. Laravel & Laravel Views는 로그인 및 등록 관련 페이지를 처리합니다.
  2. SPA는 로그인한 사용자 페이지에서 시작됩니다.
  3. my app.js는 기본 VueJS 앱을 정의합니다.mounted()로그인한 사용자의 상태(VUEX)를 설정하는 방법.이상적으로는 Larabel 백엔드에 대한 Axios 호출을 통해 사용자 세부 정보를 가져오고 VUEX 상태를 채우는 것이 전부입니다.
  4. 사용하고 있다beforeEnter()허가된 사용자만 루트로 이동할 수 있도록 루트 정의의 메서드를 지정합니다.

이것이 내가 문제에 직면한 부분이다.사용자가 로그인하면 vuex가 설정되기 전에 라우터가 실행되는 것처럼 보입니다.URL /dashboard 및 /user/1이 있다고 합니다.user/1에 접속하려고 하면 어플리케이션을 로드한 후에 정상적으로 동작합니다.단, user/1에 있을 때 웹 페이지를 새로 고치면 라우터가beforeEnter사용자의 vuex 상태를 찾을 수 없으므로 대시보드로 사용자를 리디렉션합니다.이는 라우터가 동작하고 있을 때beforeEnter신규 페이지 로드인 경우 사용자 Vuex 상태에 액세스할 수 없거나 액세스할 수 있지만 값은 아직 설정되지 않았습니다.

이 때문에 가장 큰 문제는 루트 페이지가 항상 대시보드에 도착하고 사용자가 루트로 이동해야만 작동하기 때문에 직접 링크할 수 없다는 것입니다.이 상황에 어떻게 대처해야 할까요?

이게 내가 결국 하게 된 일이야.Vue를 초기화하는 함수를 정의했습니다.

app.js의 마지막에 Axios를 사용하여 Ajax를 통해 현재 사용자를 가져옵니다.에서then약속의 방법, 나는 그것을 설정했다.store약속에서 받은 사용자 세부사항을 입력하고 위의 Vue 초기화에서 정의한 함수를 호출합니다.이렇게 하면 vue가 초기화되었을 때 스토어 사용자는 이미 데이터를 가지고 있습니다.

코드 변경은 매우 미미하여 기존 악시오 구현을 변경할 필요가 없었습니다.

이것이 새로운 구현입니다.

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

버스로 $root를 사용하고 마지막 수단으로 VueX에 접속합니다.여기 제가 작업하고 있는 플러그 인에서 몇 가지 코드를 제거했습니다.당신이 코드에 드랍할 수 있도록 약간 수정했습니다.

이 구성에서는 VUE CLI를 지원합니다.

세션 만료에 대해 걱정하지 마십시오. 가로채기는 Laravel로부터의 401 응답을 감시하면 사용자에게 재인증을 요구할 수 있습니다.

bootstrap.js에서 axios 구성을 삭제하고 이 설정으로 대체하고 액세스 제어 허용 오리진을 구성합니다. 와일드카드는 로컬 dev에 사용할 수 있습니다.

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);

    }

);

나머지는...

in 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 / Login Controller ]으로 설정합니다.php add 메서드

public final function authenticated(Request $request)
{
    return response()->json([
        'user' => Auth::user()
    ]);
}

앱/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 로그인 폼으로 효과적으로 대체할 수 있습니다.

라우터의 셋업은 다음과 같습니다.

new Router({
    mode: 'history',
    routes: [
        {
            path: '/login',
            name: 'login',
            component: AuthLogin,
            meta: {
                requiresAuth: false,
                layout: 'auth'
            }
        },
        {
            path: '/login/recover',
            name: 'login-recover',
            component: AuthLoginRecover,
            meta: {
                requiresAuth: false,
                layout: 'auth'
            }
        },
        {
            path: '/',
            name: 'index',
            component: Dashboard,
            meta: {
                requiresAuth: true,
                layout: 'default'
            }
        },
        {
            path: '/settings',
            name: 'settings',
            component: Settings,
            meta: {
                requiresAuth: true,
                layout: 'default'
            }
        }
    ]
});

언급URL : https://stackoverflow.com/questions/53703581/how-to-get-something-to-run-before-vue-router

반응형