Koa & Mongoose & Vue实现前后端分离--06前端登录&注册

上节回顾

  • 荷载的解析
  • 服务端注册&登录逻辑
  • 数据库的存储 & 查询

工作内容

  • 初始化前端环境
  • 创建前端路由
  • axios请求接口

准备工作

  • 全局安装依赖 // 以便通过vue/cli初始化项目

├── @vue/[email protected]

├── @vue/[email protected]

  • vue init webpack ./ // 先切换到/client目录下

Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第1张图片

  • npm i -S axios // 先切换到/client目录下

页面逻辑

  • npm run start查看页面是否能正常访问localhost:8080

技术选型

自己的项目,没特殊要求,选择自己熟悉的element-uiUI库、scss预编译语言快速搭建页面。

初始化页面

// 更新文件:/client/src/App.vue


// 更新文件:/client/src/router/index.js
// 顺便删除文件:/client/src/components/Helloworld.vue
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/login'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/login'
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    }
  ]
})
// 新建文件: /client/src/views/login/index.vue

展示效果 //更新不及时,可以重启前端服务
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第2张图片

引入element-uiscss

  • 安装依赖:npm i -S element-ui node-scss sass-loader@7 // sass-loader安装7.版本,目前最新版8.编译失败
  • 完整引入Element
// 更新文件:/client/src/main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'

Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: ''
})
  • 测试可用性
// 更新文件:/client/src/views/login/index.vue

  • 测试结果

Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第3张图片

快速搭建页面

为了省事,直接从Element官网 > 组件 > Form表单,拷贝一份带校验的示例改改

// 更新文件:/client/src/views/login/index.vue




// 新建文件:client/src/views/login/index.scss
.form-login {
  width: 600px;
  margin: 0 auto;
}
  • 页面展示

Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第4张图片

添加http请求

在准备工作时,已经npm i -S axios安装axios

// 新建配置文件:client/src/config/http.js
export const BASE_URL = 'http://localhost:3000/'
export const TIMEOUT = 15000
// 新建axios实例文件:client/src/utils/http.js
import axios from 'axios'
import { BASE_URL, TIMEOUT } from '@/config/http'

const instance = axios.create({
  baseURL: BASE_URL,
  timeout: TIMEOUT,
  validateStatus: function (status) {
    // return status >= 200 && status < 300; // default
    return status >= 200 // 可拦截状态码>=200的请求响应
  }
})

export default instance

注意:axios默认只返回Http Code为2**请求的响应

测试Http请求

//更新文件:server/control/users.js
async function list (ctx) {
  try {
    const users = await userModel.find(); //查出全部用户
    ctx.body = {
      code: '200',
      data: users,
      msg: '查询成功'
    }
  } catch (err) {
    ctx.body = {
      code: '403',
      data: null,
      msg: err.message
    }
  }
}
//更新文件:client/src/views/login/index.vue
...

...
  • 效果展示

Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第5张图片
发生跨域请求,这里我们切换到/server/目录下,安装依赖npm i -S koa2-cors(线上的话,可以使用nginx做代理)

// 更新文件:server/app.js
const koa = require('koa');
const bodyParser = require('koa-body');
const cors = require('koa2-cors');

const routes = require('./router');

const app = new koa();
app.use(cors());
...

重启后端服务,即可在页面http://localhost:8080/#/login看到请求结果
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第6张图片

过滤返回结果

从返回接口可以看出,请求服务端成功时,只需要res.data即可,使用instance.interceptors对返回数据进行过滤。

// 更新文件:client/src/utils/http.js
...
// Add a response interceptor
instance.interceptors.response.use(
  async res => {
    if (/^20./.test(res.status)) {
      return res.data
    }
    console.log('------response=======', res)
    return res
  },
  error => {
    return Promise.reject(error)
  }
)

export default instance

请求结果
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第7张图片

登录逻辑

//更新文件:client/src/views/login/index.vue
...
    async onLogin () {
      try {
        const valid = await this.$refs[this.formName].validate()
        if (valid) {
          const { account, password } = this.form
          const res = await http.post(
            '/users?action=login',
            {
              account,
              password,
            }
          )
          console.log(res)
          if (res && res.code === '200') {
            this.$router.replace('/home')
          } else {
            this.$message({ // 没有使用this.$message.error('')
              type: 'error',
              message: res.msg
            })
          }
        }
      } catch (err) {
        console.error(err)
      }
    },
...
  • this.$message({}),而没有使用this.$message.error(),因为发现如果res没有返回的话,会报Element的错误,造成信息误导。

更新路由文件,使登录成功跳转到Home组件

// 更新路由文件:
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/login'
import Home from '@/views/home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/login'
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    },
    {
      path: '/home',
      name: 'home',
      component: Home
    }
  ]
})
// 新建文件:client/src/views/home/index.vue

使用上节通过Postman创建的admin账户登录,结果展示
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第8张图片
缓慢的动图如下:

注册逻辑

//更新文件:client/src/views/login/index.vue
...
    async onRegister () {
      try {
        const valid = await this.$refs[this.formName].validate()
        if (valid) {
          const { account, password } = this.form
          const res = await http.post(
            '/users?action=register',
            {
              account,
              password
            }
          )
          if (res.code === '200') {
            this.$refs[this.formName].resetFields()
            this.$message({
              type: 'success',
              message: '注册成功'
            })
          } else {
            this.$message({
              type: 'error',
              message: res.msg
            })
          }
        }
      } catch (err) {
        console.error(err)
      }
    }
...

测试失败结果
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第9张图片
测试成功结果
Koa & Mongoose & Vue实现前后端分离--06前端登录&注册_第10张图片
可以使用新创建的帐号登录,发现可以成功/查看数据库,是否成功新增用户

参考文档

element-ui
vue-router
axios

你可能感兴趣的:(Koa & Mongoose & Vue实现前后端分离--06前端登录&注册)