mock+vuex+axios利用token实现用户登录验证

思路:

  1. mock模拟用户数据
  2. axios请求接口,
  3. router中进行needLogin的判断,true为需要登录才能进入此页面
  4. vuex中,将在login.vue中获取的用户名和密码进行验证
  5. 验证后,拿到token和usertitle,将token存储到sessionStorage中,usertitle存储至vuex的title,在home.vue中显示
  6. 前端每次跳转时,就在main.js使用导航守卫(vue-router.beforeEach)判断 sessionStorage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面。
  7. home.vue的退出可注销登录,注销后,就清除sessionStorage里的token信息并跳转到登录页面
    在这里插入图片描述
    mock—mock.js
import Mock from 'mockjs'
const Random = Mock.Random
//home页面的表格数据
Mock.mock('/getUser',{
    'data|3': [{
        'name': Random.cname(),
        'age': Random.natural(22, 40),
        'date': Random.date('yyyy-MM-dd'),
        'address': Random.county(true)
      }]
})
//登录数据
Mock.mock('/getLogin',
  {
    "error_code": 0,
    "data": [{
      "id": '1',
      "usertitle": "管理员",
      "username": "admin",
      "password": "123456",
      "token": "123133123",
     },
     {
      "id": '2',
      "usertitle": "用户",
      "username": "root",
      "password": "root",
      "token": "65454634",
     }
    ]
  }
)

request----http.js

import axios from 'axios';
axios.defaults.timeout = 5000;
axios.defaults.baseURL ='';
//http request 拦截器
axios.interceptors.request.use(
  config => {
    // const token = getCookie('名称');注意使用的时候需要引入cookie方法,推荐js-cookie
    config.data = JSON.stringify(config.data);
    config.headers = {
      'Content-Type':'application/x-www-form-urlencoded'
    }
    // if(token){
    //   config.params = {'token':token}
    // }
    return config;
  },
  error => {
    return Promise.reject(err);
  }
);

//http response 拦截器
axios.interceptors.response.use(
  response => {
    if(response.data.errCode ==2){
      router.push({
        path:"/login",
        querry:{redirect:router.currentRoute.fullPath}//从哪个页面跳转
      })
    }
    return response;
  },
  error => {
    return Promise.reject(error)
  }
)

//  封装get方法,返回promise对象
export function get(url,params={}){
  return new Promise((resolve,reject) => {
    axios.get(url,{
      params:params
    })
    .then(response => {
      resolve(response.data);
    })
    .catch(err => {
      reject(err)
    })
  })
}
// 封装post请求
export function post(url,data = {}){
  return new Promise((resolve,reject) => {
    axios.post(url,data)
         .then(response => {
           resolve(response.data);
         },err => {
           reject(err)
         })
  })
}
// 封装getAwait方法,返回async方法
export async function getAwait(url,params={}){
  let res=await axios.get(url,{params:params})
  res=res.data
  return res
}
// 封装getAwait方法,返回async方法
export async function postAwait(url,data={}){
  let res=await axios.post(url,data)
  res=res.data
  return res
}

request—api.js

import { get,getAwait} from './http'

//登录
export function getLogin(username,password){
	return get('/getLogin',username,password)
}
//home页面表格信息
export  function getUserInfo(param){
	return getAwait('/getUser',param)
}

router—index.js。设置needLogin后可自行进行验证,会发现,即使将浏览器URL地址改为/或者/home,页面不会跳到/或/home页面,只有/login能进入

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/pages/login'
import Home from '@/pages/home'

Vue.use(Router)

export default new Router({
  routes: [
    { path: '/', component: Home ,meta:{needLogin:true}},//needLogin判断是否需要登录才可以进入
    { path: '/home', component: Home ,meta:{needLogin:true}},
    { path: '/login', component: Login },
  ]
})

store—store.js。讲login.vue页面获取来的user和pwd跟mock中的username和password进行匹配,匹配成功则将相应token存储至session,usertitle存储至vuex的title,供home.vue显示使用

import Vue from 'vue';
import Vuex from 'vuex';
import { getLogin } from "../request/api.js";
import router from '../router/index'
Vue.use(Vuex);

const state = {
    ruleForm: {
        user:'',
        pwd:''
    },
   result:null,
   title:''
}
const mutations={
    setLogin(state,param){
        state.result=param.result
    },
    setUser(state,n){
        state.ruleForm.user=n
    },
    setPwd(state,n){
        state.ruleForm.pwd=n
    },
}
const actions={
    getLogin(context){
        getLogin().then(res => {
            console.log(res.data);
            context.commit('setLogin',{result:res.data})
            let len = res.data.length;
            let userNameArr = [];
            let passWordArr = [];
            let ses = window.sessionStorage;
            for (var i = 0; i < len; i++) {
              userNameArr.push(res.data[i].username);
              passWordArr.push(res.data[i].password);
            }
            if (userNameArr.indexOf(state.ruleForm.user) === -1) {
              alert("账号不存在!");
            } else {
              var index = userNameArr.indexOf(state.ruleForm.user);
              if (passWordArr[index] === state.ruleForm.pwd) {
                // 把token放在sessionStorage中
                ses.setItem("data", res.data[index].token);
                console.log(ses,'ses')
                state.title=res.data[index].usertitle
                //跳转到首页
                router.push("/");
              } else {
                alert("密码错误!");
              }
            }
          });
    },
    loginOut(){
        // 注销后 清除session信息 ,并返回登录页
        window.sessionStorage.removeItem('data');
        router.push('/login'); 
    }
}
export default new Vuex.Store({
    state,
    mutations,
    actions
})

pages----login.vue


<template>
  <div id="login">
    <el-form
      :model="ruleForm"
      status-icon
      :rules="rules"
      ref="ruleForm"
      label-width="100px"
      class="demo-ruleForm"
    >
      <el-form-item label="账号" prop="user">
        <el-input type="text" v-model="ruleForm.user" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="pwd">
        <el-input type="password" v-model="ruleForm.pwd" autocomplete="off" @keyup.enter.native="submitForm"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
        <el-button @click="resetForm('ruleForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { getLogin } from "../request/api.js";
import axios from "axios";
export default {
  name: "Login",
  data() {
    return {
      ruleForm: {
        user:'',
        pwd:''
      },
      rules: {
        user: [{ required: true, trigger: "blur" }],
        pwd: [{ required: true, trigger: "blur" }]
      },
    };
  },
  computed: {
    user: {
      get() {
        return this.$store.state.ruleForm.user;
      },
      set(newVal) {
        this.$store.commit("setUser", newVal);
      }
    },
     pwd: {
      get() {
        return this.$store.state.ruleForm.pwd;
      },
      set(newVal) {
        this.$store.commit("setPwd", newVal);
      }
    },
  },
  created() {

  },
  methods: {
    submitForm(formName) {
      this.user=this.ruleForm.user
      this.pwd=this.ruleForm.pwd
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          this.$store.dispatch('getLogin')
        } else {
          console.log("用户名或密码错误");
        }
      });
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

登录页面
在这里插入图片描述
pages—home.vue

<template>
  <div id="login">
    <h1>{{this.$store.state.title}}</h1>
    <el-button @click="loginOut">退出</el-button>
     <el-table
      :data="tableData"
      style="width: 100%">
       <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
       <el-table-column
        prop="age"
        label="年龄"
        width="180">
      </el-table-column>
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import {getUserInfo} from '../request/api.js'
export default {
  name: 'Home',
  data () {
    return {
      tableData:[]
    }
  },
  created(){
    getUserInfo().then(res => {
    console.log(res)
    this.tableData = res.data
  })

  },
  methods:{
    loginOut(){
      this.$store.dispatch('loginOut')
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

home.vue登录后页面,按退出则清除session信息,并返回登录页
在这里插入图片描述
main.js
在这里插入图片描述

  • 2
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
作为语言模型,我无法实际编写和运行代码,但我可以向您介绍Vue 3和Vite以及如何使用它们编写ToduList应用程序的步骤。 Vue 3是一个流行的JavaScript框架,用于构建交互式应用程序和用户界面。它具有易于学习和使用的API和一些新功能,例如Composition API和Teleport。 Vite是一个快速的现代构建工具,专为大型Web项目而设计。它提供了快速的开发服务器和即时热更新功能。 现在,让我们开始使用Vue 3和Vite构建ToduList应用程序的步骤。 第一步:安装Vite 使用npm安装Vite ``` npm install -g vite ``` 第二步:创建Vue 3项目 通过在终端中运行以下命令,在新的Vue 3项目中使用Vite ``` npm init vite@latest my-todo-list ``` 或使用npx安装和创建一个新的Vue 3项目 ``` npx create-vite-app my-todo-list --template vue ``` 这将创建一个名为' my-todo-list '的新目录并初始化一个基本的Vue 3项目结构。 第三步:安装和配置所需的依赖项 使用以下命令安装axios,用于从后端API获取数据 ``` npm install axios ``` 在'todo list/src'文件夹里新建一个'Api.js'文件: ``` import axios from 'axios' const apiClient = axios.create({ baseURL: `http://localhost:8000/`, // change to API URL headers: { Accept: 'application/json', 'Content-Type': 'application/json' } }) export default { getTodos() { return apiClient.get('/todos') }, editTodoStatus(id, data) { return apiClient.put(`/todos/${id}`, data) }, addNewTodo() { return apiClient.post('/todos') }, deleteTodoById(id) { return apiClient.delete(`/todos/${id}`) } } ``` 第四步:定义应用程序 编辑'todo list/src/App.vue'文件 ``` <template> <div class="container"> <h1 class="text-4xl text-center my-8"> TODO LIST </h1> <div class="my-8"> <button @click.prevent="addNewTodo" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Add New Todo </button> </div> <div class="my-8"> <ul> <li v-for="todo in todos" :key="todo.id" class="mb-4"> <div class="flex justify-between items-center"> <div> <input type="checkbox" :checked="todo.completed" @change="toggleCompletion(todo)" class="mr-2" /> <span class="font-bold">{{todo.title}}</span> </div> <div class="flex"> <button class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg" @click.prevent="deleteTodoById(todo.id)"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5"> <path fill-rule="evenodd" d="M14.823 1.77a.75.75 0 01-.06 1.06L10.56 6.25l4.204 4.424a.75.75 0 11-1.12 1.012L9.25 7.812l-4.344 4.575a.75.75 0 01-1.12-1.012L7.93 6.25.765 1.832a.75.75 0 111.06-1.06L9.25 5.688l5.573-5.918a.75.75 0 011.001-.106z" clip-rule="evenodd" /> </svg> </button> </div> </div> </li> </ul> </div> </div> </template> <script> import Api from '@/Api' export default { name: 'App', data() { return { todos: [] } }, async created() { await this.fetchData() }, methods: { async fetchData() { const { data: todos } = await Api.getTodos() this.todos = todos }, async toggleCompletion(todo) { await Api.editTodoStatus(todo.id, { completed: !todo.completed }) await this.fetchData() }, async addNewTodo() { await Api.addNewTodo() await this.fetchData() }, async deleteTodoById(id) { await Api.deleteTodoById(id) await this.fetchData() } } } </script> <style> /* ... */ </style> ``` 第五步:运行程序 使用以下命令运行程序 ``` npm run dev ``` 现在在浏览器中访问'http:// localhost:3000'即可看到ToduList应用程序。 可以使用Api.js文件里的接口完成每操作,此处用axios调用后台API进行模拟,并未真正实现后端API。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值