Vue+Vant+Koa2+MongoDB实现用户注册

        今天我们来实现一个用户注册的页面,在上一篇入门教程的基础上新增代码(当前的项目目录结构请参考上一篇教程),我们将原先 Vue 生成的默认页面中 About 页面替换为 注册页面 (效果图如下) 。我们从零开始,从最初的新建前端表单,到数据的后端验证存储,检测数据库中是否已经存在注册用户,若存在则提示 “该用户已注册” ,若不存在则提示 “注册成功” 。

     

一、前端部分

前端运用  Vue + Vant,首先我们完成第一步,编写 Register 表单

 

1.1 我们在 mall\src\components 目录下新建 Register.vue 文件,

 

 在 <template> </template> 标签内添加:

<div id="register">
    <van-form>
      <van-field
        v-model="username"
        label="用户名"
        placeholder="请输入用户名"
        :rules="[{required: true, message: '请填写用户名'}]"
      />
      <van-field
        v-model="password"
        type = "password"
        label="密码"
        placeholder="请输入密码"
        :rules="[{required: true, message: '请输入密码'}]"
      />
      <van-field
        v-model="telnumber"
        label="手机号码"
        placeholder="请输入手机号码"
        :rules="[{required: true, message: '请输入手机号码'}]"
      />

      <div style="margin: 16px;">
        <van-button square block type="info" native-type="submit" size="normal" @click="onSubmit">
          提交
        </van-button>
      </div>
    </van-form>
  </div>

 

 注:在表单中,除了提交按钮外,可能还有一些其他的功能性按钮,如发送验证码按钮。在使用这些按钮时,要注意将 native-type 设置为 button ,否则会触发表单提交。

        这个问题的原因是浏览器中 button 标签 type 属性的默认值为submit,导致触发表单提交。我们会在下个大版本中将 type 的默认值调整为 button 来避免这个问题。

 

在 <script> </script> 标签内添加:

import { Field } from 'vant';
import { Button } from 'vant';
import { Toast } from 'vant';
import { Form } from 'vant';
  
export default {
  components:{
    [Field.name]: Field,
    [Button.name]: Button,
    [Toast.name]: Toast,
    [Form.name]: Form,
  },
  data() {
    return {
      username: '',
      password: '',
      telnumber: ''
    }
  }
}

 

1.2 修改 router\index.js,

顶端添加 :

import Register from '../components/Register.vue'

 

添加 routes 路由参数:

{
  path: '/register',
  name: 'Register',
  component: Register
},

 

1.3 修改 App.vue :

<router-link to="/about">About</router-link>

将上面的代码修改为:

<router-link to="/register">注册</router-link>

 

此时,重新运行 Vue 项目,可以看到页面:

 

 

二、 通过 axios 实现前端向后端传递数据

当用户填写完毕注册信息,点击提交按钮后,前端会将注册信息通过 axios 发送给后端服务器,并获取到返回信息,具体实现如下:

 

2.1 在 Register.vue 中 新增 提交按钮事件:

import ajax from  '@/api';  //首先引入ajax类  
methods: {
  async onSubmit() {                      // async修饰符非常重要,表示该函数为异步执行
    let { username, password, telnumber } = this.$data;     //获取表单中的数据
    let res = await ajax.register(username, password, telnumber);       //await表示该语句等待 await后的语句有返回了之后,再接着执行 onSubmit的语句
    console.log(res)                     
  },
}

也许你会发现 ajax.register 目前为止还是未定义的,不着急,接下来我们就会编写 ajax 类。

 

2.2 编写 ajax 类,修改 mall\src\api\index.js ,添加如下代码:

// 注册 | POST
  register(username, password, telnumber) {
    return axios.post('http://localhost:3000/users/registerUser',{username, password, telnumber})
  }

 

 OK,到这里我们的前端部分就基本完成了,下面我们进行后端部分开发。

 

三、后端 Koa2 部分

 

后端部分的主要实现逻辑:

1> 新建 user 数据集合存储用户信息,  

2> 编写 router.post 路由接收前端数据,

3> 后端验证注册信息并存储返回

 

 3.1 新建 mongDB 数据集合

在 mall-server 文件夹下新建 models 文件夹,新建 user.js :

const mongoose = require('mongoose');

var Schema = mongoose.Schema;
var userSchema = new Schema({
 username: {type: String, unique: true},
 password: String,
 telnumber: String
});

module.exports = mongoose.model('User',userSchema)

 

进一步,我们不可以直接存储明文密码,这样安全性得不到保障,因此在存储前,需要对密码进行加密,用的 bcryptjs,在 user.js 里继续添加:

const bcrypt = require('bcryptjs'); // 用于密码哈希的加密算法
/**
 * 对密码进行加盐
 * 使用 pre 中间件在用户信息存储前执行
 */
userSchema.pre('save', function(next) {
  // 进行加密 | 产生一个 salt
  bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) => {
    if (err) return next(err);
    // 结合 salt 产生新的hash
    bcrypt.hash(this.password, salt, (err, hash) => {
      if (err) return next(err);
      // 使用 hash 覆盖明文密码
      this.password = hash;
      next();
    });
  });
});

 

此时我们的数据模型已经新建完毕,若对 mongoDB 不熟悉的小伙伴,可以翻阅我之前的文章有介绍说明。

 

3.2 编写 router.post 路由接收前端数据

修改 routes\user.js , 添加代码:

const userService = require('../service/user');                     //引入userService类 会在下一步编写,主要用于向数据库中存储用户注册信息
router.post('/registerUser', async function (ctx) {
  let {username, password, telnumber} = ctx.request.body;           //koa-bodyparser 解析request.body
  if(!username || !password || !telnumber) return ctx.body = {code: 4020,msg: '请填写完整的注册信息'};    
  
  let args = {username, password, telnumber};
  const userData = await userService.accountHandle(args);           //userService类会在下一步编写
  
  ctx.body = (userData.code === 200) 
     ? {code: 200, msg: '注册成功'} 
     : userData
})

 

3.3  编写 userService 类,用于后端验证注册信息并存储返回

在 mall-server 文件夹下新建,user.js :

const UserModel = require('../models/user')            //引入 model

class userService {
  async accountHandle({username, password, telnumber}) {
    const user = await UserModel.findOne({username})
    if (user) return { code: 0, msg: '该用户已经注册' };     //若用户已存在,停止向下执行,并返回错误提示信息

    let userEntity = new UserModel({ username, password, telnumber });
      // 保存到数据库中
      let userInfo = await userEntity.save();
      return {
        code: 200,
        username: userInfo.username,
        password: userInfo.password,
        telnumber: userInfo.telnumber
      }
  }
}

module.exports = new userService();          // 导出这个类,注意与ES6导出类写法的差别

 

OK ,到这里,我们就基本实现了用户注册的功能,当然还有不完善的地方,比如需要添加手机号正则验证、短信验证码、axios 添加响应拦截器、JWT 认证,将会在下面的文章中一起研究。当然,有不正确的地方,欢迎大家留意指正。

posted @ 2020-05-26 15:26  几行  阅读(572)  评论(1编辑  收藏  举报