Вход в Vuex через наблюдателя - PullRequest
0 голосов
/ 27 сентября 2018

Итак, я работаю над проектом, в котором я использую Vuex и vue-router.При входе в систему в настоящий момент страница обновляет состояние и перезагружает страницу после нажатия на кнопку входа в систему и снова переходит в / вход в систему.Получив изменение данных от наблюдателя, он перенаправляет пользователя в / home путь.Я хочу выполнить загрузку без перехода к / входу в систему при получении данных, поскольку это выглядит странно.

В моем файле store / index.js у меня есть этот код:

const state = {
  user: null,
  loading: false
}

const getters = {
  user: state => state.user,
  loading: state => state.loading
}

const actions = {
  me : ({ commit }) => {
    commit('setLoading', true)
      apolloClient
        .query({
          query: GET_CURRENT_USER
        })
        .then(({ data }) => {
          setTimeout(() => {
          commit('setLoading', false)
          // Add user data to state
          commit('setUser', data.me)
          console.log(data)
          }, 500)
        })
        .catch(err => {
          commit('setLoading', false)
          console.log(err)
        })
  },

  login: ({ commit }, payload) => {
      localStorage.setItem('token', '')
      apolloClient
        .mutate({
          mutation: LOGIN,
          variables: payload
    })
    .then(({ data }) => {
        setTimeout(() => {
        localStorage.setItem("token", data.login.auth.token)
        router.go('/')
        VueNotifications.success({ message: 'Welcome !' }) 
        }, 500)       
      })
    .catch(err => {
      VueNotifications.error({ message: 'Error' });
    })
  },

  logout : async ({ commit }) => {
    Nprogress.start();
      // clear user in state
      commit('clearUser')
      // remove token in localStorage
      localStorage.setItem('token', '')
      // end session
      await apolloClient.resetStore()
      // redirect to home - kick users out of private pages
      router.push('/session/login')
      Nprogress.done();

  }
}

const mutations = {
  setUser: (state, payload) => {
      state.user = payload
    },
  setLoading: (state, payload) => {
      state.loading = payload
  },
  clearUser: state => (state.user = null)
}

Кроме того, Login.vue выглядит следующим образом:

    computed: {
    ...mapGetters(['loading', 'user'])
    },
    created() {
        this.$store.dispatch('me')    
    },
    watch: {
        deep: true,
        immediate:true,
    user(value) {
      if(value) {
        this.$router.push('/')
            } 
    }
  },
  methods: {        
        loginUser() {
      if(this.$refs.form.validate()) {
      this.$store.dispatch("login", {
        email: this.email,
        password: this.password
        }) 
      }
        }
  }

Наконец, main.js похож на это, что делает реализацию vue-router

router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        // this route requires auth, check if logged in
        // if not, redirect to login page.
        if (!store.getters.user) {
            next({
                path: '/session/login',
            })
        } else {
            next()
        }
    } else {
        next() // make sure to always call next()!
    }
})

Любая помощь приветствуется, спасибо!

1 Ответ

0 голосов
/ 01 октября 2018

внутри вашего верхнего компонента в beforeCreated hook для обновления информации о пользователе при загрузке страницы:

this.$store.dispatch('user/fetch')

внутри вашего пользовательского модуля хранилища:

const getters = {
  ...
  profile: state => state.profile,
  signedIn: state => Boolean(state.token && state.profile)
  ...
}

позже в том же пользовательском модуле в действиях:

async signIn ({ dispatch }, fields = {}) {
  try {
    // requesting user token
    ...

    await dispatch('setToken', response.data['auth_token'])

    // this function can be removed by using "vuex-persistedstate"
    localStorage.setItem('token', response.data['auth_token'])
    await dispatch('fetch') // fetch user profile after sign in

    router.push({ path: config.redirect.afterSignInPath })

    // success message 'Welcome!'
    ...
  } catch (e) {
    // error message 'login failed'
    ...
  }
},

setToken ({ commit }, token) {
  commit(SET_TOKEN, token)     
  // set auth token for all requests (in axios, for example)
  ...
},

// fetch user profile data with token
async fetch ({ commit, dispatch, getters }) {
  dispatch('fetchTokenFromLS')
  let token = getters['token']
  if(!token)  
    return

  try {
    // requesting user profile
    // commiting it to the store
    ...

  } catch (e) {
    VueNotifications.error({ message: 'Error' });
  }
},

// this can be removed by using "vuex-persistedstate"
async fetchTokenFromLS ({ dispatch }) {
  // try to extract token from localStorage
  let token = localStorage.getItem('token')

  if (token)
    await dispatch('setToken', token)
},

paths.signInPath = '/ session / login'

paths.afterSignInPath = '/ home'

import store from '~/store'    
...

router.beforeEach((to, from, next) => {
  let pageRequiresAuth = to.matched.some(record => record.meta.requiresAuth)
  let nextParams
  let userSignedIn = store.getters['user/signedIn']

  if (pageRequiresAuth) {
    if (!userSignedIn) 
      nextParams = { path: paths.signInPath }
  } else {
    // login page doesn't require auth.
    // don't let the user see login page if it's already signed in.
    if (userSignedIn) 
      nextParams = { path: paths.afterSignInPath }
  }
  next(nextParams)
}

После всех изменений, которые вам не нужнынаблюдатель пользователя на домашней странице больше

...