javascript - 练习题:AJAX用户登录(nodejs服务响应)
原创
©著作权归作者所有:来自51CTO博客作者ahuiok的原创作品,请联系作者获取转载授权,否则将追究法律责任
需求描述
前端页面用户登录,ajax 发送请求,后台验证,并响应请求;
数据交互
前后分离,先后端再前端;
前端开发
login.html: 登录页面
index.html: 跳转页面
login.js: 前端请求页面
Web服务
server.js: 后端接口 node.js
登录过程
前端
1)前端要获取账号密码;
2)请求参数做签名加密;
3)发送登录请求;
后端
1)拿到参数;
2)验证返回;
后端服务
使用 node.js 的 express 框架来实现 web 服务并验证请求;
后端不是本贴的重点:只是为了完成前端的数据响应
需要安装 node.js 和引入 express 框架:
node.js 官网:https://nodejs.org/en/
express 官网: http://expressjs.com/ 或 https://www.npmjs.com/package/express
> npm install express -S
> npm install body-parser -S
新建 server.js : web 服务环境,
var express = require('express'); // 引入框架
var bodyParser = require('body-Parser'); // 引入依赖
var app = express();
// 数据解析
app.use(bodyParser.json()); // 对 json 数据解析
app.use(bodyParser.urlencoded({ extended: true })) // 对表单数据解析
// 跨域
var allowCrossDomain = function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*'); // 自定义中间件,设置跨域需要的响应头
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE'); // 允许任何方法
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-Width,content-type,X-Session-Token');
next();
}
app.use(allowCrossDomain);
// 端口
app.listen(2999, function () {
console.log("sever has Started ............");
});
// 登录模拟接口 地址:http://localhost:2999/user/login
app.post('/user/login', function (req, resp) {
var { username, password } = req.body;
if (username && password) {
if (username == "admin" && password == "admin") {
resp.status(200).send("登录成功!");
} else {
resp.status(400).send("用户名或密码错误!");
}
} else {
resp.status(400).send("获取用户名或密码参数失败!");
}
});
启动后端服务:
启动后端服务后,显示:“sever has started ... ” 代表正常启用,等待响应了;
测试接口: postman 来测试
postman 官网: https://www.postman.com/
现在还没有前端,所以使用 postman 来测试接口好不好用:
使用,红、黄、蓝、绿、黑的箭头顺序依次:
红:选择 POST 发送请求;
黄:输入新建的web服务地址;
蓝:选请求体 body , JSON ;
绿:输入 json 格式的数据;
黑:发送请求;
最后得到 “登录成功!” 的返回结果;
也可以只写 用户名或密码,或错误的数据来反复测试接口可用性,这个简易的接口目前没问题;
前端编码
先写个 login.html 页面;
<div class="content">
<div class="login">
<form id="login-form" action="" method="GET">
<div class="inputs">
<label for="">用户</label>
<input type="text" id="username" placeholder="请输入用户名" required>
<div class="text-err">
<div class="text-msg"></div>
<div class="triangle"></div>
</div>
</div>
<div class="inputs">
<label for="">密码</label>
<input type="password" id="password" placeholder="请输入密码" required>
<div class="pass-err">
<div class="pass-msg"></div>
<div class="triangel"></div>
</div>
</div>
<button type="button" id="submit">登录</button>
</form>
</div>
</div>
<script src="login.js"></script>
只包括一个表单和一个引入的js文件,我们的重点就在 login.js 文件;
login.html 页面长这样:
我们将通过 login.js 的前端代码来实现与后端服务交互;
面对过程:新手写法;
let submitBtn = document.querySelector("#submit");
submitBtn.addEventListener('click', function () {
let username = document.querySelector("#username").value;
let password = document.querySelector("#password").value;
login(username, password);
});
function login(username, password) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log(xhr.responseText);
} else {
alert('请求失败');
}
}
}
xhr.open("POST", "http://localhost:2999/user/login");
xhr.setRequestHeader('Content-Type', 'application/json'); // 请求头
xhr.send(JSON.stringify({ username: username, password: password }));
}
面向对象:工程师写法;
var LoginObj = {
init() { // 初始化
let submitBtn = document.querySelector("#submit");
submitBtn.addEventListener('click', () => { // 绑定事件,箭头函数
let username = document.querySelector("#username").value;
let password = document.querySelector("#password").value;
if (username && password) {
this.sendLoginRequest(username, password); // this指向 LoginObj
} else {
alert("账号或密码不能为空");
}
});
},
sendLoginRequest(username, password) { // 发送请求
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () { // 事件监听
if (xhr.readyState == 4) {
if (xhr.status == 200) {
// 拿到后端数据
console.log(xhr.responseText);
// 跳转 location'
location.href = "./index.html";
} else {
alert('请求失败');
}
}
}
xhr.open("POST", "http://localhost:2999/user/login");
xhr.setRequestHeader('Content-Type', 'application/json'); // 请求头 json 类型
xhr.send(JSON.stringify({ username: username, password: password }));
}
}
面向对象,还可以封装公共请求:高手写法;
var LoginObj = {
init() { // 初始化
let submitBtn = document.querySelector("#submit");
submitBtn.addEventListener('click', () => {
let username = document.querySelector("#username").value;
let password = document.querySelector("#password").value;
if (username && password) {
this.sendLoginRequest(username, password);
} else {
alert("账号或密码不能为空");
}
});
},
sendLoginRequest(username, password) { // 发送请求
var xhr = createXMLHttp();
xhr.sendRequest({
method: "POST",
url: "http://localhost:2999/user/login",
jsonData: { username: username, password: password },
sucCallback: function () {
console.log(xhr.responseText);
location.href = "./index.html";
},
errCallback: function () {
alert('请求失败,请联系管理员');
}
});
}
}
// 封装公共请求,使用了闭包,看起来高大上了;
function createXMLHttp() {
var xhr = new XMLHttpRequest();
return {
// 把可变的属性抽出来;
// method -- post
// url -- 地址;
// jsonData -- 请求数据
// sucCallback -- 成功回调
// errCallback -- 失败回调
sendRequest({ method, url, jsonData, sucCallback, errCallback }) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
sucCallback();
} else {
errCallback();
}
}
}
xhr.open(method, url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(jsonData));
}
}
}
window.onload = function () {
LoginObj.init();
}
测试结果:
只输入用户名:账户或密码不能空;
错误的用户名和密码:请求失败,请联系管理员;
正确的用户名和密码:就直接跳转 index.html ;