前言
在上一篇文章中我们通过引入mysql2/promise
将Node.js应用与MySQL数据库连接,利用连接池,SQL查询,验证用户输入的账号和密码,实现了账号和密码在数据库中的校验。
本篇内容将优化代码,加入状态码与异常处理。实现便捷登录后,重点实现注册功能:通过线程池查询数据库防重复注册,再执行插入,成功后跳转登录页,确保注册数据可登录。
一,优化代码
在上篇文章中我们成功实现用户与数据库的交互,当用户输入正确的账号密码时后端会返回从数据库中查询返回的结果( result) 。接下来我们需要对程序运行中可能出现的情况做出判断并将信息传给前端。
1. 登入成功 我们对result做个判断,如果这个数据不为空(数据库中对应的数据有对应值)我们就将所有信息给到data,然后将她放在响应体ctx.body
中返回给前端。
2. 账号不存在
如果没有检索到对应值就说明账号和密码错误,同样用ctx.body返回对应信息给前端。
3. 服务器异常
当出现网络,软件等问题导致数据请求失败时给前端报错,指明错误原因不在前端。
4. 错误捕获
当出现程序之外的原因导致的错误时我们需要使用 try{}catch(err){} 捕获错误
5. 状态码
我们需要指定对应的状态码,这样能快速的为我们的项目找出问题所在。在这里,定义8000为登录成功状态码,8004指明账号密码不存在,8005指明服务器异常。
改进后的代码确保了程序的健壮性和稳定性
js
try {
// 去数据库进行校验
const result = await userLogin(username, password)
console.log(result);
if (result.length) {
let data = {
id: result[0].id,
nickname: result[0].nickname,
username: result[0].username
}
ctx.body = {
code: '8000',
msg: '登录成功',
data: data,
}
} else {
ctx.body = {
code: '8004',
msg: '登录失败,账号或密码错误'
}
}
} catch (err) {
ctx.body = {
code: '8005',
msg: '服务器异常',
data: err
}
}
})
通过前端打印可以顺利得到对应的信息
二,浏览器本地存储
为了提升用户体验,浏览器支持将用户输入的账号密码安全地存储在本地。这样,当用户再次访问同一网站并需要登录时,浏览器能自动检索并填充登录表单,简化登录流程,实现快速、便捷的访问体验。
js
localStorage.setItem('userInfo', JSON.stringify(res.data))
三,跳转到首页
当用户登入成功时,跳转到对应页面。在这里设置为首页路由为 /noteClass
js
import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/noteClass')
四,设计注册页面
当用户没有账号密码时,我们为用户提供一个注册页面 /register
在登入页面提示这一段代码,实现点击按钮时跳转到注册页面
js
<p class="register" @click="() => router.push('./register')">
新用户?点击这里注册</p>
设计注册页面,配置路由。
页面布局设计
js
<template>
<div class="login">
<h1>注册</h1>
<div class="login-wrapper">
<div class="avatar">
<img src="../assets/2.gif" alt="">
</div>
<van-form @submit="onSubmit">
<van-cell-group inset>
<van-field v-model="nickname" type="text" name="nickname" label="昵称" placeholder="昵称"
:rules="[{ required: true, message: '请填写昵称' }]" />
<van-field v-model="username" name="username" label="用户名" placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]" />
<van-field v-model="password" type="password" name="password" label="密码" placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]" />
</van-cell-group>
<div style="margin: 16px;">
<van-button round block type="primary" native-type="submit">
注册
</van-button>
</div>
</van-form>
</div>
<p class="register" @click="router.push('/login')">已有账号?点击这里登录</p>
</div>
</template>
js
<style lang="less" scoped>
.login {
width: 100vw;
height: 100vh;
background-color: #fff;
padding: 0 0.3rem;
box-sizing: border-box;
overflow: hidden;
position: relative;
h1 {
height: 0.6933rem;
text-align: center;
font-size: 0.48rem;
margin-top: 1.12rem;
}
.login-wrapper {
width: 7.44rem;
height: 10.77rem;
border: 1px solid rgba(187, 187, 187, 1);
margin: 0 auto;
margin-top: 1.7rem;
border-radius: 0.3rem;
box-shadow: 0 0 0.533rem rgba(170, 170, 170, 1);
.avatar {
width: 2.4rem;
height: 2.4rem;
margin: 1rem auto 0.77rem auto;
// border-radius: 50%;
overflow: hidden;
background-size: cover;
img {
width: 100%;
}
}
}
.register {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
font-size: 0.374rem;
color: rgba(16, 16, 16, 1);
}
}
:deep(.van-cell__title.van-field__label) {
width: 45px;
}
</style>
实现效果如下:
整理一下我们的思路,我们在上面已经实现了用户输入正确账号时的路由跳转,输入正确账号将跳转到 /noteClass
页面;当输入账号密码错误时可以选择注册账号,所以我们接下来需要实现的功能是------用户可以注册账号密码昵称,用户注册成功后可以通过注册的账号密码登入/noteClass
页面。
将用户注册的数据插入到数据库中是我们接下来需要实现的功能
五,注册页面中的前后端数据库交互
注册页面,给后端发送消息。和前面的篇章一样,在设计登入页面的时候同样要进行这样的操作。引入我们封装的axios , 通过post将用户输入的昵称nickname账号和密码发送给后端,后端再通过连接池和sql语句查询验证。
前端注册页面拿到后端数据
js
import { ref } from 'vue'
import axios from '@/api/index.js'
import { useRouter } from 'vue-router'
import { showSuccessToast, showFailToast } from 'vant';
const nickname = ref('')
const password = ref('')
const username = ref('')
const router = useRouter()
const onSubmit = async (values) => {
// 拿到注册表单数据
console.log(values);
// 发送接口请求给后端 ,后端在数据库校验
const res = await axios.post('/user/register', values)
// 校验成功,显示成功轻提示
showSuccessToast(res.msg)
// 当注册成功时,等待1.5s,使得用户看到注册成功的轻提示,再跳转到登入页面
setTimeout(() => {
router.push('/login')
}, 1500)
}
后端利用数据池进行sql操作
后端接受注册页面传递过来的消息,在是数据库中进行判断,是不是很熟悉?
我们需要连接数据库,但这次需要实现的功能是在数据库中查找数据如果没有对应数据就插入,这就需要使用SQL的插入语法。
js
// 查账账号
const userFind = (username) => {
let _sql = `SELECT * FROM users WHERE username="${username}";`
return allServices.Query(_sql)
}
// 检测注册页面用户的输入,如果数据库中没有数据存储则插入
const userRegister = (username, password, nickname) => {
let _sql = `INSERT INTO users(username,password,nickname) VALUES("${username}","${password}","${nickname}");`
return allServices.Query(_sql)
}
后端验证前端输入的信息
1. 如果传入的信息有空的,则返回 msg = '账号密码或昵称不能为空'
2. 利用我们配置好的方法userFind检测当前账号是否已经存在,如果已经有其他用户注册过则显示 msg: '账号已存在'
3. 账号不存在,可以注册, 利用userRegister方法存储到数据库中
4. 利用userRegister方法成功插入数据后返回的 affectedRows=1判断是否成功插入
5. 成功插入则返回注册成功,不然返回注册失败
6. 使用try{}catch(){}捕获其他可能出现的错误
js
router.post('/register', async (ctx) => {
// 获取到前端传递的账号密码,准备存储到数据库中
const { username, password, nickname } = ctx.request.body;
// 校验账号密码和昵称是否为空
let msg = ''
if (!username || !password || !nickname) {
msg = '账号密码或昵称不能为空'
ctx.body = {
code: '8001',
msg: msg
}
return
}
try {
// 校验账号是否存在
const findRes = await userFind(username)
// 账号已存在
if (findRes.length) {
ctx.body = {
code: '8003',
msg: '账号已存在',
data: 'error'
}
return
}
// 账号不存在,可以注册, 存储到数据库中
const registerRes = await userRegister(username, password, nickname)
console.log(registerRes);
// 后台打印的registerRes.affectedRows=1 显示影响了一条数据,意为插入成功
// 如果成功插入了数据的话,为前端返回注册成功的提示
if (registerRes.affectedRows) {
ctx.body = {
code: '8000',
msg: '注册成功',
data: 'success'
}
} else {
ctx.body = {
code: '8004',
msg: '注册失败',
data: 'error'
}
}
} catch (err) {
ctx.body = {
code: '8005',
msg: '服务器异常',
data: err
}
}
})
数据库中验证
在注册页面测试,输入数据1,1,1。观察MYSQL发现我们刚刚注册的数据全被写入数据库中。
恭喜! 账号注册成功!即将为您跳转登入页面!
小计
在这节课的学习中我们首先对上节课的代码进行了优化,添加自己定义的状态码使得我们能够定位我们在全栈开发出现的错误, 使用try{}catch(err){} 捕获错误使得我们的代码更加健壮。
之后我们利用浏览器的本地储存实现了便捷登入,配置了登入成功之后的页面和注册页面
接下来是我们这篇文章的重点:实现用户的注册功能。我们需要利用已经构建好的线程池对数据库进行sql查询工作,确保用户输入的账号无人注册过;之后在执行sql插入语法,将用户的输入插入到数据库中,确保无误后跳转到登入页面,用户输入刚刚注册的数据可以实现成功登入。
本期要点:try{}catch(err){},状态码,浏览器的本地储存,sql查询语法,sql插入语法