[Vue.js] vue user login function

Before using Vue to implement the login function of a website, here is a record and summary. The following is the description of the login business that needs to be implemented:

1. Enter the user name and password, and click the login button. If the two match, you can enter the home page, and the home page displays the information of the logged-in user;

2. After the user logs in, the login page cannot be accessed;

3. The user is not logged in and cannot access the page that needs to be logged in to be displayed. At this time, it needs to jump to the login page. After the login is successful, it will directly jump to the page that the user clicked to access just now.

1. Basic login function realization

First, briefly introduce the login logic, the sequence diagram is as follows:

The login button is bound to the click event handleLogin. First, the front-end verification is performed, which is to check the standardization of the user name and password. It can be analyzed in detail according to the specific needs of the needs, such as making a regular judgment, or sending a request to verify whether it exists, etc., which will not be implemented in detail here. Only judge whether the user enters, and then dispatch vuex, the action is userLogin, the main code of login.vue is as follows:

data(){
      return {
        phone:'',
        password:''
      }
    },
async handleLogin(){
  const {phone,password} = this;
  try {
     phone && password && await this.$store.dispatch('userLogin',{phone,password});
     let toPath = this.$route.query.redirect || 'home';
     this.$router.push(toPath);
  } catch (error) {
     alert(error.message);
  }
}

In userLogin, call the encapsulated reqLogin method to send a login request to the backend interface. The response result of the request is two types. If the user name and password are correct, return token (a string for verifying user information), if the login fails, return reason of failure.

Here, async and await modifiers are used to process asynchronous requests. The async modified method userLogin will return a Promise instance. Here, the Promise returned by userLogin is the result of success or failure to inform the login.vue component of the login behavior. When the login is successful, first let vuex save the token, but the vuex data will be lost after refreshing, so it is also necessary to save the token information in the browser's local storage and return a non-Promise type. If the login fails, a failed Promise is returned, and the reason for the failure is thrown as an exception.

Then, in the login component login.vue, judge the return result of userLogin. Since the await modifier is used to handle asynchronous operations, and it can only obtain successful Promises, use try...catch...to obtain the failure of await As a result , the reason pops up on the page when the login fails.

After success, use $router.push(toPath) to jump to the home page.

Vuex code:

import {reqGetCode,reqRegister,reqLogin,reqUserInfo,reqUserLogout} from '@/api'
const state = {
    code:'',
    // vue仓库存储数据不是持久化的,刷新数据丢失
    token:localStorage.getItem('TOKEN') || '',
    userInfo:{}
};
const mutations = {
    USERLOGIN(state,token){
        state.token = token;
    },
    USERINFO(state,userInfo){
        state.userInfo = userInfo || {};
    },
};
const actions = {
    async userLogin(context,data){
        // 发送登录请求
        let result = await reqLogin(data);
        if(result.code === 200) {
            // 存放token,vuex和localStorage各一份
            context.commit('USERLOGIN',result.data.token);
            localStorage.setItem('TOKEN',result.data.token);
            return 'ok';
        } else {
            // 登录失败
            return Promise.reject(new Error(result.message));
        }
    },
}

Token is a token, which is a valid credential for the server to identify the login user information. When the login is successful, the server returns to the front end. It is generally stored in the local storage, and is put in the request header and submitted to the server together in the request after login, so that The server verifies the legitimacy of the logged-in user's identity. After jumping to the home page, you need to send a request to obtain user information. At this time, you need to submit the token you just obtained to the server, and you need to make a second encapsulation of the axios request , as follows:

import axios from 'axios'
// 引入进度条
import nprogress from 'nprogress'
// 引入进度条的样式
import 'nprogress/nprogress.css'
// 引入store
import store from '@/store'
// 创建axios实例
const requests = axios.create({
    // 配置对象
    // 基础路径
    baseURL:"/api",
    // 请求超时的时间
    timeout:5000,
});

// 请求拦截器 -- 在请求发出前做些事情
requests.interceptors.request.use((config) => {
    // 需要携带token给服务器
    if(store.state.user.token) {
        config.headers.token = store.state.user.token;
    }
    nprogress.start();
    // config 是配置对象,里面包含请求头headers
    return config;
});

// 响应拦截器 
requests.interceptors.response.use((res) => {
    nprogress.done();
    return res.data;
},(err) => {
    return Promise.reject(new Error('fail'))
});

export default requests;

The core is to add a request header token to each request after login in the request interceptor of axios : config.headers.token = store.state.user.token

Send a request on the home page

<template>
    <p v-if="!userName">
        <span>请</span>
        <router-link to="/login">登录</router-link>
        <router-link to="/register" class="register">免费注册</router-link>
    </p>
    <p v-else>
        <a href="#">{
   
   {userName}}</a>
        <a href="#" class="register" @click="logout">退出登录</a>
    </p>
</template>


<script>
export default {
  name:"home",
  mounted(){
    this.getUserInfo();
    
  },
  computed:{
    userName(){
      let userInfo = this.$store.state.user.userInfo;
      return userInfo.name || '';
    }
  }
  methods:{
    getUserInfo(){
        try {
          await this.$store.dispatch('getUserInfo');
        } catch (error) {
          // alert(error.message);
        }
    }
  }
}
</script>

vuex:

const state = {
    userInfo:{}
};
const mutations = {
    USERINFO(state,userInfo){
        state.userInfo = userInfo || {};
    },
};   
const actions = {
    // 获取用户信息(token)
    async getUserInfo(context){
        let result = await reqUserInfo();
        if(result.code === 200) {
            context.commit('USERINFO',result.data);
            return 'ok';
        } else {
            return Promise.reject(new Error(result.message));
        }
    },
}

2. Use routing guards to intercept unlogged

The basic login function has been realized above, but some optimizations still need to be made, such as the need to jump to the login page after login, and the interception function of pages related to user information when not logged in, here you need to use the routing global of vue- router Guarded , the configuration of the global guard is generally carried out in the routing configuration file, usually in the routes/index.js file in the project.

What needs to be done is to use the global pre-guard router.beforeEach before the routing jump to judge the redirected page and login status. The specific judgment logic is as follows:

 routes/index.js:

import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
import store from '@/store'

// 使用路由插件
Vue.use(VueRouter);
// 配置路由
const router = new VueRouter({
    // 配置路由
    routes,
    // 滚动行为
    scrollBehavior(to, from, savedPosition) {
        // return 期望滚动到哪个的位置
        // y:0代表垂直滚动条在最上方
        return {y:0};
    }
});
// to:获取到跳转的那个路由信息;
// from:获取到哪个路由而来的信息;
// next:放行函数,
// 	next('/login'):放行到指定的路由
// 	next(false):返回到起始的路由
router.beforeEach(async (to,from,next) => {
    let token = store.state.user.token;
    if(token) {
        // 登录
        if(to.path === '/login') {
            // 登陆后访问登录页
            next({path:from.path});
        } else {
            // 登陆后访问非登录页
            if(!store.state.user.userInfo.name) {
                // 当空对象作为判断条件时,相当于true。当空对象与布尔值直接比较时,相当于true,但空数组与布尔值直接比较时是false
                // 登录后访问非登录页,如果此时用户信息由于页面刷新,store为空需要再次请求后端,拿到用户信息
                try {
                    await store.dispatch('getUserInfo');
                    next();
                } catch (error) {
                    // token过期
                    await store.dispatch('userLogout');
                    next({path:'/login'});
                }
            } else {
                // 登录后访问非登录页,无刷新操作
                next();
            }
        }
    } else {
        // 未登录
        if(to.path.indexOf('/pay') ==! -1 || to.path.indexOf('trade') !== -1 || to.path.indexOf('center') !== -1) {
            next(`/login?redirect=${to.path}`);     
        } else {
            next();
        }
    }
});

export default router;

One more thing to note here is that when the user is not logged in and clicks on a page that requires login to access, it will jump to the login page, but after successful login, it needs to jump directly to the page just clicked instead of the home page , so here When jumping to the landing page, pass the parameter through query, that is : next(`/login?redirect=${to.path}`) , pass the redirected routing path to.path to the login page , after successful login Use programmatic routing to navigate this.$router.push(this.$route.query.redirect) to jump.

Guess you like

Origin blog.csdn.net/weixin_43655896/article/details/122787629