上一篇文章讲到的是如何利用mongoose从数据库读取数据然后更新页面,接下来要实现的就是用户注册登录功能,这个功能涉及到的东西太多了,今天只实现了登录功能,登陆之后更新导航条界面,最后效果如下:
登录之前:
登陆之后(用户名:oujiamin):
这是登陆界面(还没有设置css):
主要实现步骤:
1、校验
所谓校验就是对用户的输入进行限制并且给出一点提示,这里使用的是vee-validate插件,该插件主要作用就在于可以很方便地绑定input标签并且给出校验规则和提示语,使用步骤:
安装:npm install --save-dev vee-validate
在main.js引入:import VeeValidate, { Validator } from 'vee-validate'
默认为英文提示,所以要修改成中文:import zh from 'vee-validate/dist/locale/zh_CN.js'
最后:Validator.addLocale(zh)
const config = {
locale: "zh_CN"
}
Vue.use(VeeValidate, config)
完成此步骤后,vee-validate插件已经可以使用了,在需要的组件处使用:
<template>
<div id="login">
<h1>Login</h1>
<form id="login">
<div>
<input v-validate="'required|alpha_num|min:6'" v-model="username" type="text" name="username" id="email" placeholder="请输入用户名" />
<span class="tips" v-show="errors.has('username')">{{ errors.first('username')}}</span>
</div>
<div>
<input v-validate="'required|alpha_num|min:8'" v-model="password" type="text" name="password" id="password" placeholder="请输入密码" />
<span class="tips" v-show="errors.has('password')">{{ errors.first('password')}}</span>
</div>
<input type="button" @click="checked" value="提交" />
</form>
</div>
</template>
主要看input标签处,在input标签上添加属性v-validate=""就可以使用,里面的属性值‘required|alpha_num|min:6’分别表示:
alpha_num:输入必须为字母或者数字
min:6:输入最少长度为6
注意:v-validate=""的属性必须再用''括起来,不然不会有提示语句,我就是被这个坑了很长时间。关于vee-validate更详细的用法,可以参考博客:
最后效果如下:
2、使用vue-resource发送post请求进行登录操作,这里在component文件夹新建了一个Login.vue文件,就是上面的Login界面
首先“提交“按钮绑定checked()方法:<input type="button" @click="checked" value="提交" />
在组件下定义checked方法:
methods: {
checked: function() {
this.$validator.validateAll().then((result) => {
// 如果输入不满足条件,则阻止提交表单
if(!result) {
return false
} else {
var userData = {
username: this.username,
password: this.password
}
this.$http.post('query/userLogin', userData).then(function(response) {
response = response.body
// 根据返回的errno采取相应动作
// errno:0 表示成功登陆,跳转到MainPage,并且更新主页面
this.setUser(response.data.username, true)
})
}
})
}
这里实现的效果有两个,第一个是在校验规则不通过的情况下不允许请求发送(return false):
this.$validator.validateAll().then((result) => {
// 如果输入不满足条件,则阻止提交表单
if(!result) {
// 不发送
return false
} else {
... // 发送
}
}
第二个是发送post请求,判断账号是否存在数据库并且获得该账号信息:
this.$http.post('query/userLogin', userData).then(function(response) {
response = response.body
this.setUser(response.data.username, true)
})
注意这里的setUser方法,这里是假设账号合法并且已经成功把账号信息返回之后所执行的操作,目的在于把username返回给App.vue页面,更新导航条界面(隐藏登录/注册按钮,显示用户名)实现的方法也不复杂,利用了父子组件之间传递数据的方法。在Login.vue组件(子组件)定义setUser方法,post请求得到返回数据之后调用setUser方法,把username传递过去,第二个参数true是为了给App.vue页面的v-show判断然后改变状态。下面是setUser方法代码:
setUser: function(msg, check) {
this.$emit('transferUser', msg, check)
}
接下来需要在App.vue界面(父组件)响应该方法并且更新界面,如下:
<router-view @transferUser='getUser'></router-view>
上面使用getUser方法响应transferUser,transferUser就是子组件传递过来的值,下面定义getUser方法:
methods: {
getUser: function(msg, check) {
this.username = msg
this.check = check
this.$router.push("/MainPage")
}
}
最后一句是”this.$router.push("/MainPage")“,表示路由自动触发跳转到MainPage页面。App.vue完整代码如下:
<template>
...
<div id="login-page">
<router-link to="/Login" v-show="!check">登录/注册</router-link>
<span v-show="check">{{username}}</span>
<router-view @transferUser='getUser'></router-view>
</div>
</template>
<script>
import Login from '@/components/Login.vue'
export default {
name: "app",
data() {
return {
check: false,
username: ""
}
},
methods: {
getUser: function(msg, check) {
this.username = msg
this.check = check
this.$router.push("/MainPage")
}
},
components: {
Login
}
}
</script>
上述是在post请求成功情况下实现的操作,成功与否还需要根据校验结果来判定。已经事先在数据库创建了users集合并且插入了一条信息,主要两条数据:username和password
下面是修改build/dev-server.js文件代码:
先是创建了userSchema和userModel(上一篇讲到的,使用Mongoose的方法),利用userModel.find方法获得数据库数据,并且在回调函数中执行操作,data就是数据库返回的数组对象
usersModel.find({}, function(error, data) {
...
}
在函数中绑定路由的post请求:
queryRoutes.post('/userLogin', function(req, res) {
...
}
然后再post请求的回调函数里面判断用户名和密码是否符合:
var resData = data.concat()
var resUser = {} //返回匹配用户对象
var reqData = req.body
var username = req.body.username
var password = req.body.password
for(var key in resData) {
if(username === resData[key].username) {
if(password === resData[key].password) {
resUser = {
username: resData[key].username,
password: resData[key].password
}
res.send({
errno: 0,
data: resUser
})
} else {
res.send({
errno: 1,
data: "密码错误"
})
}
}
}
res.send({
errno: 2,
data: "用户不存在"
})
简单解释一下,利用for循环遍历resData数组(resData就是data的一个复制数组,不是把地址赋值给它,而是复制了一份新的),当发现username === resData[key].username的时候,表示该用户名已经存在,进一步判断密码是否相等,相等则直接返回data数据,errno置为0。不相等表示密码错误,返回字符串”密码错误“,errno置为1,如果都不想等则直接返回”用户不存在“,errno置为2。
完整代码:
usersModel.find({}, function(error, data) {
queryRoutes.get('/user', function(req, res) {
res.send({
errno: 0,
data: data
})
})
queryRoutes.post('/userLogin', function(req, res) {
var resData = data.concat()
var resUser = {} //返回匹配用户对象
var reqData = req.body
var username = req.body.username
var password = req.body.password
for(var key in resData) {
if(username === resData[key].username) {
if(password === resData[key].password) {
resUser = {
username: resData[key].username,
password: resData[key].password
}
res.send({
errno: 0,
data: resUser
})
} else {
res.send({
errno: 1,
data: "密码错误"
})
}
}
}
res.send({
errno: 2,
data: "用户不存在"
})
})
})
app.use('/query', queryRoutes)
这里有一个问题需要注意就是使用express.router模块发送post请求的时候,一直在后台接收req为空,这里需要在代码前面添加:
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
至此已经实现了用户登录功能,后面将要实现用户注册以及相应的音乐收藏,评论等与用户有关的功能。