使用vue搭建应用六实现登录页

1.js_cookie

js-cookie插件是一个JS操作cookie的插件

安装

yarn add js-cookie

 使用

  写入 Cookies.set('name', 'value');

  读取 Cookies.get('name');

  删除 Cookies.remove('name');

2.http请求

(1)模块封装

  在src下添加目录 utils,添加 global.js

/**
 * 全局常量、方法封装模块
 * 通过原型挂载到Vue属性
 * 通过 this.Global 调用
 */
export const baseUrl = 'http://localhost:8081'

export default {
  baseUrl
}

  在src下添加目录 http

  config.js

import { baseUrl } from '@/utils/global'

export default {
  method: 'get',
  // 基础url前缀
  baseUrl: baseUrl,
  // 请求头信息
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // 参数
  data: {},
  // 设置超时时间
  timeout: 10000,
  // 携带凭证
  withCredentials: true,
  // 返回数据类型
  responseType: 'json'
}
View Code

  axios.js axios封装

import axios from 'axios';
import config from './config';
import Cookies from "js-cookie";
import router from '@/router'

export default function $axios(options) {
  return new Promise((resolve, reject) => {
    const instance = axios.create({
      baseURL: config.baseUrl,
      headers: config.headers,
      timeout: config.timeout,
      withCredentials: config.withCredentials
    })
    // request 请求拦截器
    instance.interceptors.request.use(
      config => {
        let token = Cookies.get('token')
        // 发送请求时携带token
        if (token) {
          config.headers.token = token
        } else {
          // 重定向到登录页面
          router.push('/login')
        }
        return config
      },
      error => {
        // 请求发生错误时
        console.log('request:', error)
        // 判断请求超时
        if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
          console.log('timeout请求超时')
        }
        // 需要重定向到错误页面
        const errorInfo = error.response
        console.log(errorInfo)
        if (errorInfo) {
          error = errorInfo.data  // 页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.reject
          const errorStatus = errorInfo.status; // 404 403 500 ...
          router.push({
            path: `/error/${errorStatus}`
          })
        }
        return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息
      }
    )

    // response 响应拦截器
    instance.interceptors.response.use(
      response => {
        return response.data
      },
      err => {
        if (err && err.response) {
          switch (err.response.status) {
            case 400:
              err.message = '请求错误'
              break
            case 401:
              err.message = '未授权,请登录'
              break
            case 403:
              err.message = '拒绝访问'
              break
            case 404:
              err.message = `请求地址出错: ${err.response.config.url}`
              break
            case 408:
              err.message = '请求超时'
              break
            case 500:
              err.message = '服务器内部错误'
              break
            case 501:
              err.message = '服务未实现'
              break
            case 502:
              err.message = '网关错误'
              break
            case 503:
              err.message = '服务不可用'
              break
            case 504:
              err.message = '网关超时'
              break
            case 505:
              err.message = 'HTTP版本不受支持'
              break
            default:
          }
        }
        console.error(err)
        return Promise.reject(err) // 返回接口返回的错误信息
      }
    )
    // 请求处理
    instance(options).then(res => {
      resolve(res)
      return false
    }).catch(error => {
      reject(error)
    })
  })
}
View Code

  modules/login.js  系统登录模块

// 登录接口
export function login() {

  const loginData = {
    "code": 304,
    "msg": "登录失败",
    "data": {
      "id": 1,
      "userId": 1,
      "token": "1111111111"
    }
  }
  /*
  const loginData = {
    "code": 200,
    "msg": "登录成功",
    "data": {
      "id": 1,
      "userId": 1,
      "token": "1111111111"
    }
  }
  */
  return {
    url: 'login',
    type: 'post',
    data: loginData
  }
}
// 登出接口
export function logout() {
  const logoutData = {
    "code": 200,
    "msg": null,
    "data": {
    }
  }
  return {
    url: 'logout',
    type: 'get',
    data: logoutData
  }
}
View Code

  api.js 接口统一集成模块

import * as login from './modules/login'

export default {
  login
}
View Code

  index.js  导入所有接口

import api from './api'

const install = Vue => {
  if (install.installed)
    return;

  install.installed = true;

  Object.defineProperties(Vue.prototype, {
    // 注意,此处挂载在 Vue 原型的 $api 对象上
    $api: {
      get() {
        return api
      }
    }
  })
}

export default install

(2)应用

  main.js

webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import api from './http'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.config.productionTip = false

Vue.use(ElementUI)
Vue.use(api)  // 注册使用API模块

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

3.登录

  view/login.vue

<template>
  <el-form
    :model="loginForm"
    :rules="fieldRules"
    ref="loginForm"
    label-position="left"
    label-width="0px"
    class="demo-ruleForm login-container"
  >
    <span class="tool-bar"></span>
    <h2 class="title" style="padding-left:22px;">系统登录</h2>
    <el-form-item prop="account">
      <el-input type="text" v-model="loginForm.account" auto-complete="off" placeholder="账号"></el-input>
    </el-form-item>
    <el-form-item prop="password">
      <el-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="密码"></el-input>
    </el-form-item>
    <el-form-item style="width:100%;">
      <el-button type="primary" style="width:48%;" @click.native.prevent="reset">重 置</el-button>
      <el-button
        type="primary"
        style="width:48%;"
        @click.native.prevent="login"
        :loading="loading"
      >登 录</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
import Cookies from "js-cookie";
export default {
  name: "Login",
  data() {
    return {
      loading: false,
      loginForm: {
        account: "admin",
        password: "admin"
      },
      fieldRules: {
        account: [{ required: true, message: "请输入账号", trigger: "blur" }],
        password: [{ required: true, message: "请输入密码", trigger: "blur" }]
      },
      checked: true
    };
  },
  methods: {
    login() {
      this.loading = true;
      let userInfo = {
        account: this.loginForm.account,
        password: this.loginForm.password
      };
      this.$api.login
        .login(userInfo)
        .then(res => {
          // 调用登录接口
          if (res.code != 200) {
            this.$message({ message: res.msg, type: "error" });
          } else {
            this.$message({ message: res.msg, type: "success" });
            console.log(res);
            Cookies.set("token", res.data.token); // 放置token到Cookie
            sessionStorage.setItem("user", userInfo.account); // 保存用户到本地会话
            this.$router.push("/"); // 登录成功,跳转到主页
          }
          this.loading = false;
        })
        .catch(res => {
          this.$message({ message: res.message, type: "error" });
        });
    },
    reset() {
      this.$refs.loginForm.resetFields();
    }
  }
};
</script>

<style lang="scss" scoped>
.login-container {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  -moz-border-radius: 5px;
  background-clip: padding-box;
  margin: 100px auto;
  width: 350px;
  padding: 35px 35px 15px 35px;
  background: #fff;
  border: 1px solid #eaeaea;
  box-shadow: 0 0 25px #cac6c6;
  .title {
    margin: 0px auto 30px auto;
    text-align: center;
    color: #505458;
  }
}
</style>
View Code

4.测试

mock封装

  在src下添加目录 mock

  index.js

import Mock from 'mockjs'
import { baseUrl } from '@/utils/global'
import * as login from './modules/login'

// 1. 开启/关闭[所有模块]拦截, 通过调[openMock参数]设置.
// 2. 开启/关闭[业务模块]拦截, 通过调用fnCreate方法[isOpen参数]设置.
// 3. 开启/关闭[业务模块中某个请求]拦截, 通过函数返回对象中的[isOpen属性]设置.
let openMock = true
// let openMock = false
fnCreate(login, openMock)

/**
 * 创建mock模拟数据
 * @param {*} mod 模块
 * @param {*} isOpen 是否开启?
 */
function fnCreate(mod, isOpen = true) {

  if (isOpen) {
    for (var key in mod) {
      ((res) => {
        if (res.isOpen !== false) {
          let url = baseUrl
          if (!url.endsWith("/")) {
            url = url + "/"
          }
          url = url + res.url
          Mock.mock(new RegExp(url), res.type, (opts) => {
            opts['data'] = opts.body ? JSON.parse(opts.body) : null
            delete opts.body
            console.log('\n')
            console.log('%cmock拦截, 请求: ', 'color:blue', opts)
            console.log('%cmock拦截, 响应: ', 'color:blue', res.data)
            return res.data
          })
        }
      })(mod[key]() || {})
    }
  }
}
View Code

modules/login.js  系统登录模块

// 登录接口
export function login() {

  const loginData = {
    "code": 304,
    "msg": "登录失败",
    "data": null
  }
  return {
    url: 'login',
    type: 'post',
    data: loginData
  }
}

启动执行 npm  run dev

浏览器打开 http://localhost:8080/#/login

 

 修改modules/login.js

// 登录接口
export function login() {
  const loginData = {
    "code": 200,
    "msg": "登录成功",
    "data": {
      "id": 1,
      "userId": 1,
      "token": "1111111111"
    }
  }
  return {
    url: 'login',
    type: 'post',
    data: loginData
  }
}

 

posted @ 2019-11-15 18:58  慕尘  阅读(505)  评论(0编辑  收藏  举报