前面我们已经可以连接后端数据库,现在就可以直接进行功能的实现了。
这一节是注册功能的实现。
注册方面:
首先是前端数据的表单验证,验证传入后端数据的合法性。(使用正则验证)
用户名:2-18位字母或数字组合且不能与已有数据重复(这个需要异步与后端进行交互,下一篇文章里讲了具体实现)
密码:6-18位字母或数字组合
昵称:少于13位中文字母或数字组合且不能与已有数据重复
学校:4位以上中文全称
头像上传:el-upload的钩子,:before-upload,验证大小2M与是否jpg格式
附上正则:
/^[0-9a-zA-Z]*$/g 这个是验证是否只有数字和字母,防止出现其他符号
/^([\u4e00-\u9fa5]){4,20}$/ 这个是验证是否输入的是4-20位中文
/^[a-zA-Z0-9\u4e00-\u9fa5]+$/ 这个是验证输入是否仅包含中文、字母和数字
例(element的自定义表单验证方法):
var validateUser = (rule, value, callback) => {
var reg= /^[0-9a-zA-Z]*$/g;
if (value === '') {
callback(new Error('请输入用户名'));
}else if(value.length>18 || value.length<2){
callback(new Error('长度在2-18位'));
} else if(!reg.test(value)){
callback(new Error('请只包含字母数字'));
} else {
callback();
}
};
关于图片的上传,第一次接触,原生input标签里有个type=file属性,点击就会自动调用系统文件夹点击上传。由于我使用的是el-upload,在el-upload标签里直接写上传的地址即可(不用加localhost:3000!)。
这里有一点需要注意:点击上传图片之后出去,再次点击注册按钮发现图片还在表单里,这是不对的,再次点击注册应该清空所有表单信息,这里需要在el-upload控件里加上ref=’upload’ ,然后在注册方法里加上this.$refs.upload.clearFiles(),同时清空后端发来的保存图片地址的变量。
上传的逻辑为:点击upload,图片即上传到后端服务器(后端使用formidable插件进行接收),更名为系统时间加随机数(保证唯一性)存到后端文件夹headImg下,返回给前端文件名,前端保存这个名字,前端点击提交,检验是否全部填写以及图片是否存在(根据保存的文件名是否为空判断),若存在,将所有变量post到后台。
后端保存了图片之后前端通过url的方式访问,在这里后端需要在app.js中将headImg这个文件夹暴露出来供前端访问即加上
app.use(express.static(path.join(__dirname, ‘headImg’)));
这样就可以通过访问localhost:3000/+保存图片名 直接访问到后端图片。
<el-upload
ref='upload'
action="/users/headImg"
list-type="picture-card"
:limit="1"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
使用axios传到后端
axios.post("/users/register",{
userHeadImg:req.body.userHeadImg,
userName:this.registerForm.registerUserName,
userPwd:this.registerForm.pass,
userSchool:this.registerForm.school,
userNickName:this.registerForm.nickName
}).then((response)=>{
//这里是返回之后发生的回调
})
后端
router.post("/register",function(req,res,next){
User.find({},(err,doc)=>{ //遍历数据库里的所有文档
var param = new User({
userHeadImg:req.body.userHeadImg,
userId:20180000+doc.length,//以文档数组的长度作id,保证唯一性
userName:req.body.userName,
userPwd:req.body.userPwd,
userSchool:req.body.userSchool,
userNickName:req.body.userNickName
});
param.save((err)=>{
if (err) {
res.json({
status:"1",
msg:err.message
})
}else{
res.json({
status:"0",
msg:'suc'
})
}
})
})
})
router.post("/headImg",function(req,res,next){
var form = new formidable.IncomingForm();
form.uploadDir = './headImg/temp'; //上传临时文件夹
form.maxFieldsSize = 2 * 1024 * 1024;//最大上传大小2M
form.parse(req,(err,fields,files)=>{
if(err){
res.json({
status:"1",
msg:'upload err!'
})
}
//console.log(files)
//成功后的回调
//下面是将临时文件重命名并转移到headImg文件夹下
//使用第三方模块silly-datetime
var t = sd.format(new Date(),'YYYYMMDDHHmmss');
//生成随机数
var ran = parseInt(Math.random() * 8999 +10000);
//拿到扩展名
var extname = path.extname(files.file.name);
fs.renameSync(files.file.path, 'headImg/'+t+ran+extname,(err)=>{
if(err){
res.json({
status:"2",
msg:'upload(change name) err!'
})
throw Error("改名失败");
}
}); //重命名,将原本存进temp的乱码文件重命名转移到headImg文件夹下
res.json({
status:"0",
msg:t+ran+extname
})
})
});
注意的是前后端传入的变量名要相同。
用户的id,生成这个并要保证唯一性比较麻烦,如果同时两个人写入数据库就会有相同的id,后面如果要验证的话可能需要id和用户名同时验证。。。
也没想到什么好的方法生成用户id,一开始的想法是找到最后插入的数据然后加1就行,但是好像不太好找到最新的(网上说插入的时候也是无序插入,所以有一定的漏洞)。后来用了数组下标的唯一性,每次遍历一遍整个文档,记录文档数组长度,将数组的index赋给用户id,但是这样应该挺耗费性能的,要不再看看网上的解决方案,如何生成用户id。
至此注册功能完成。