【Vuex+localStorage】登录时获取token并封装api接口:

  • Post author:
  • Post category:vue




1.思路:
1.login.vue
2.api=>login.js
3.router=>index.js
4.store=>index.js
5.utils=>rquest.js和storage.js和utils.js
6.退出设置


2.login.vue
/* 
    登录页面
 */
<template>
    <div class="loginMain">
        <!-- 导航栏 -->
        <van-nav-bar title="登录" left-text="返回" left-arrow @click-left="$router.back()" />

        <!-- 登录表单 -->
        <van-form ref="loginForm" @submit="handleSubmit()">
            <van-field v-model="username" name="用户名" label="用户名" placeholder="用户名" :rules="rulesFrom.username" />
            <van-field v-model="password" type="password" name="密码" label="密码" placeholder="密码"
                :rules="rulesFrom.password" />
            <van-field v-model="mobile" type="number" name="mobile" maxlength="11" placeholder="手机号"
                :rules="rulesFrom.mobile">
                <!-- <template #left-icon>
                    <i class="iconfont icon-shouji"></i>
                </template> -->
                <i slot="left-icon" class="iconfont icon-shouji"></i>
            </van-field>
            <van-field v-model="code" name="code" placeholder="验证码" :rules="rulesFrom.code" left-icon="closed-eye">
                <template #button>
                    <van-count-down :time="1000 * 10" format="ss 秒/s" v-if="isCountDownShow"
                        @finish="isCountDownShow = false" />
                    <van-button v-else type="primary" size="small" @click="handleGetCode()">获取验证码</van-button>
                </template>
            </van-field>
            <div style="margin: 16px;">
                <van-button block type="info" @click="handleSubmit()">登录</van-button>
            </div>
        </van-form>
    </div>
</template>

<script>
import { loginAPI } from '@/api/login'

export default {
    data() {
        return {
            username: '',
            password: '',
            mobile: '',
            code: '',
            rulesFrom: {
                username: [{ required: true, message: '请填写用户名' }],
                password: [{ required: true, message: '请填写密码' }],
                mobile: [{ required: true, message: '请填写手机号' }, { pattern: /1[3|5|7|8]\d{9}/, message: '手机号格式输入错误' }],
                code: [{ required: true, message: '请填写验证码' }, { pattern: /^\d{6}$/, message: '验证码格式输入错误' }],
            },
            isCountDownShow: false,
        }
    },
    methods: {
        // 获取验证码
        async handleGetCode() {
            const that = this
            // 1、验证手机号
            try {
                await that.$refs.loginForm.validate('mobile')
            } catch (error) {
                return console.log('验证失败', error)
            }

            // 2、验证通过,显示倒计时
            that.isCountDownShow = true

            // 3、请求发送验证码

        },
        // 登录按钮
        async handleSubmit() {
            const that = this
            that.$toast.loading({
                message: '登录中...',
                forbidClick: true,//禁止背景点击
                duration: 0, // 持续展示,默认2000
            })
            let param = {
                username: that.username,
                password: that.password
            }
            const res = await loginAPI(param)
            if (res.data.code == 0) {
                // 处理Token
                that.$store.commit('setUser', res.data.data)
                // 登录成功
                that.$toast.success('登录成功')
                // 跳转页面
                that.$router.back()
                that.$router.push({ path: '/home' }).catch(() => { });
            } else if (res.data.code == 400) {
                that.$toast.fail('验证码过期,请稍后重试')
            } else {
                // 登录失败
                that.$toast.fail('登录失败,请稍后重试')
            }
        },
    }
}
</script>

<style scoped lang="less">
.loginMain {
    width: 100%;
    height: 100%;
}
</style>


3.api=>login.js
import request  from '@/utils/request';


// 登录
export function loginAPI(obj) {
    return request({
        url: '/api/user/login',
        methods: 'post',
        data:obj
    })
};


4.router=>index.js
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'login',
    component: () => import(/* webpackChunkName: "login" */ '@/views/login')
  },
  {
    path: '/',
    name: 'layout',
    component: () => import(/* webpackChunkName: "layout" */ '@/views/layout'),
    children: [
      {
        path: '/home',
        name: 'home',
        component: () => import(/* webpackChunkName: "home" */ '@/views/home')
      }, {
        path: '/message',
        name: 'message',
        component: () => import(/* webpackChunkName: "message" */ '@/views/message')
      }, {
        path: '/video',
        name: 'video',
        component: () => import(/* webpackChunkName: "video" */ '@/views/video')
      }, {
        path: '/mine',
        name: 'mine',
        component: () => import(/* webpackChunkName: "mine" */ '@/views/mine')
      }
    ]
  },
  {
    path: '/search',
    name: 'search',
    component: () => import(/* webpackChunkName: "search" */ '@/views/search')
  }
]

const router = new VueRouter({
  routes
})

export default router


5.store=>index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { getItem, setItem } from '@/utils/storage'

Vue.use(Vuex)

const TOKEN_KEY = 'Token'  //设置Token本地存储名称为常量

export default new Vuex.Store({
  state: {
    // user: null,//一个对象,存储当前用户登录信息(Token等数据)
    // user: JSON.parse(window.localStorage.getItem(TOKEN_KEY))
    user: getItem(TOKEN_KEY)
  },
  mutations: {
    setUser(state, data) {
      state.user = data

      // 防止刷新丢失
      // window.localStorage.setItem(TOKEN_KEY, JSON.stringify(state.user))
      setItem(TOKEN_KEY, state.user)
    }
  },
  actions: {
	 //系统登出
	 LogOut({ commit, reject }) {
		return new Promise((resolve) => {
			commit('setUser', null);
			resolve();
		}).catch(error => {
			reject(error)
		})
	 },
  },
  modules: {

  }
})


6.utils=>rquest.js和storage.js和utils.js
/* 
    请求模块配置文件
*/
import axios from "axios";
import store from '@/store/index'
import {Message, MessageBox} from 'element-ui'

const request = axios.create({
    baseURL: 'http://192.168.8.237:8002/',
    timeout: 2000,
})

// 请求拦截器
request.interceptors.request.use(function (config) {

    const { user } = store.state
    if (user && user.token) {
        config.headers['token'] = user.token
        // config.headers.Authorization = `Bearer ${user.token}`
    }
    
    return config
}, function (error) {
    return Promise.reject(error)
})


//响应拦截器
request.interceptors.response.use(response => {
  const res = response.data;

  if (res.code && res.code == 500) {
    Message({
      message: res.msg || res.message,
      type: 'error'
    })
  } else if (res.state && res.state == 500) {
    Message({
      message: res.msg || res.message,
      type: 'error'
    })
  } else if (res.msg && res.msg.indexOf('过期') != -1) {
    MessageBox.confirm('登录已过期 请重新登录', '提示', {
      confirmButtonText: '重新登录',
      type: 'warning'
    }).then(() => {
      store.dispatch('LogOut').then(() => {
        location.href = '/login';  //跳转到登录页面
      })
    })
  }

  return Promise.resolve(response)
}, error => {
  Message({
    message: error.message,
    type: 'error',
    duration: 5 * 1000
  })
  return Promise.reject(error)
})

export default request
// 封装本地存储操操作模块

// 存储数据
export const setItem = (key, value) => {
  // 将数组、对象类型的数据转换为 JSON 格式字符串进行存储
  if (typeof value === 'object') {
    value = JSON.stringify(value)
  }
  window.localStorage.setItem(key, value)
}

// 获取数据
export const getItem = key => {
  const data = window.localStorage.getItem(key)
  try {
    return JSON.parse(data)
  } catch (err) {
    return data
  }
}

// 删除数据
export const removeItem = key => {
  window.localStorage.removeItem(key)
}



6.退出时和使用存储当前用户登录信息:
/* 
    我的页面
 */
<template>
    <div class="mineMain">
        <header>
            <!-- 登录 -->
            <div class="Login" v-if="user">
                <div class="loginTop">
                    <div class="loginInfo">
                        <van-image class="avator" round fit="cover" src="https://img01.yzcdn.cn/vant/cat.jpeg" />
                        <span>SunPeng</span>
                    </div>
                    <van-button type="default">编辑资料</van-button>
                </div>
                <div class="loginBottom">
                    <div class="ebox">
                        <span>8</span>
                        <span>收藏</span>
                    </div>
                    <div class="ebox">
                        <span>8</span>
                        <span>收藏</span>
                    </div>
                    <div class="ebox">
                        <span>8</span>
                        <span>收藏</span>
                    </div>
                    <div class="ebox">
                        <span>8</span>
                        <span>收藏</span>
                    </div>
                </div>
            </div>

            <!-- 未登录 -->
            <div class="noLogin" @click="$router.push('/login')" v-else>
                <img src="" alt="">
                <span><i>登录</i>/<i>注册</i></span>
            </div>
        </header>

        <section>
            <van-grid :column-num="2" class="gridNav" clickable>
                <van-grid-item dot>
                    <i slot="icon" class="iconfont icon-shoucang"></i>
                    <span slot="text">收藏</span>
                </van-grid-item>
                <van-grid-item icon="photo-o" text="历史" badge="99+" />
            </van-grid>

            <van-cell title="设置" label="描述信息" clickable />
            <van-cell title="消息通知" icon="location-o" value="内容" is-link arrow-direction="down" />
            <van-cell is-link>
                <template #title>
                    <span class="custom-title">小智同学</span>
                    <van-tag type="danger">标签</van-tag>
                </template>
                <template #right-icon>
                    <van-icon name="search" class="search-icon" />
                </template>
            </van-cell>
            <van-button v-if="user" type="primary" block @click="handleLoginOut()">退出登录</van-button>
        </section>
    </div>
</template>

<script>
import { mapState } from 'vuex';//获取用户信息,判断是否登录

export default {
    name: 'Mine',
    data() {
        return {

        }
    },
    computed: {
        ...mapState(['user'])
    },
    created() {

    },
    methods: {
        // 退出登录
        handleLoginOut() {
            const that = this
            this.$dialog.confirm({
                message: '确认退出登录吗?'
            }).then(() => {
                // on confirm  清除登录状态(容器+本地)
                that.$store.commit('setUser', null)
            }).catch(() => {
                // on cancel
                console.log('取消登录')
            })
        },
    }
}
</script>


api一些接口的写法



版权声明:本文为weixin_53791978原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。