エフェクト画像
序文
サーバーサイド開発の方向性を勉強している学生として、フロントエンドを勉強しましたが、深くはなく、自分の美学と相まって、フロントエンドを書くのは面倒だと個人的に感じています。本当に満足のいくインターフェースを書くことはできません。ほとんどのバックエンドプログラマーにとって、最初から作成するのではなく、既製の静的リソーステンプレートを使用して変更する必要があります。いくつかのフロントエンドフレームワークを理解していても、快適なインターフェイスを作成することはより困難です。
上記のログインフォームは非常に快適に見えます。これは私のJavaWebコースの小さな割り当てです。あまりにも醜いので、先生から提供された静的ページは使用しませんでした。。ハハハ。
フロントエンドの観点から、このようなログインフォームを実装する方法を分析します。もちろん、必要なバックエンドインターフェイスについても簡単に説明します。
詳細はコードを参照してください。コードには簡単なコメントが書かれており、注意すべき詳細が記されています。
分析
1.入力ボックス(緑色のOKプロンプト、赤色のエラープロンプトを含む)、ボタンなど。もちろん、これらのコンポーネントを自分で作成する方法がわからないため、これらのコンポーネントをそれほど美しく見せることは困難です。比較的簡単に開始できるフロントエンドフレームワークであるブートストラップを選択しました。正直なところ、具体的には調べていません。公式Webサイトにアクセスしてドキュメントを読み、コピーして貼り付けてから、微調整してください。スタイル。作成するときは、ブートストラップのレスポンシブ機能にも注意を払い、インターフェイスをモバイルデバイスに適合させる必要があります。
2.上記のgifからわかるように、このログインフォームの検証は非常に厳密で細心の注意を払っています。このフォーム検証のロジックを分析してみましょう。詳細はどれくらいですか。
検証ルール
(1)メールボックスを空にすることはできず、メールボックスは正規表現に準拠している必要があります
(2)バックエンドにメールボックスの確認を非同期的に要求します。メールボックスが存在する場合、バックエンドはアカウントのアバターのURLを返し、フロントエンドは上部のラウンドアバターを更新します。
(3)パスワードを空にすることはできません
(4)非同期検証コード
検証トリガー
入力ボックスがフォーカスを失った場合は、フォームアイテムが対応するルール(メールボックスなど、複数のルール)を満たしていることを確認してください。ルールが失敗する限り、「ログイン」ボタンをクリックしてフォームを送信することはできません。
メッセージ通知
情報プロンプトには、緑色のOKプロンプトと赤色のエラープロンプトの2種類があります。2つのプロンプトにはそれぞれ、テキストプロンプト、アイコンプロンプト、および入力ボックスの境界線の色の変更という3つの詳細が含まれています。もちろん、これらのスタイルはすべてブートストラップに由来しますが、検証トリガーと検証に基づいてスタイルの切り替えを制御する必要があります。
jqueryを使用して記述したとしても、詳細が多すぎるため、このような複雑で面倒なロジック検証を記述するのは非常に困難です。!!現時点では、jqueryベースのプラグインjquery.validation.min.jsを使用します。このプラグインは公式ウェブサイトから直接ダウンロードできます。インターネット上で他のプラグインの修正バージョンを見つけました。一般的に使用される検証ルールのいくつかが元のjquery.validationに追加されています。もちろん、これを行うのは比較的強力なフロントエンドエンジニアでなければなりません。バックエンドの学生として、私は現在この能力を持っていません。
バックエンドインターフェイス
1.メールボックスが存在するかどうかを確認し、ユーザーアバターを返します:/ account / photo
2.確認コードを生成します:/ account / captcha / generate
3.確認コードが正しいことを確認します:/ account / captcha / validate
4.ログイン:/ account / login
インターフェイスは比較的単純で、パラメータを省略しました。学習したSpringBootは簡単に記述できるはずです。学習ニーズのために、私はMavenを使用してSSMを手動で統合しました。SpringBootほど快適ではありません。
データ
Boostrap公式ウェブサイト:https://v3.bootcss.com/css/
jquery.validation拡張バージョン:https://download.csdn.net/download/qq_43290318/13109073
jquery.validationの詳細な使用法:https://blog.csdn.net/wangxiaoan1234/article/details/77466720
コード
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String contextPath = request.getContextPath();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 不设置的话,手机端不会进行响应式布局 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登录</title>
<!-- 引入Bootstrap核心样式文件(必须) -->
<link rel="stylesheet" href="lib/bootstrap/css/bootstrap.min.css">
<!-- 你自己的样式或其他文件 -->
<link rel="stylesheet" href="css/login.css">
<!--站点图标-->
<!-- ... -->
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-4 col-sm-offset-4 panel panel-default login-box">
<div class="panel-body">
<img class="img-circle photo" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1605206616385&di=5a3e31c19b07f422adf49c37505f5126&imgtype=0&src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202007%2F07%2F20200707113705_VFJvw.thumb.400_0.jpeg"
alt="头像">
<form id="loginForm" onSubmit="return false;">
<!--
关于bootstrap输入框提示
父容器div的has-feedback不能少,has-success和has-error选其一
-->
<div class="form-group has-feedback">
<label for="email">邮箱</label>
<!-- 错误提示信息 -->
<span class="error-msg"></span>
<input type="email" class="form-control" id="email" name="email" placeholder="邮箱">
<!-- 图标,打勾或者打叉。glyphicon-ok和glyphicon-remove -->
<span class="glyphicon form-control-feedback"></span>
</div>
<div class="form-group clear-float has-feedback">
<label for="password">密码</label>
<span class="error-msg"></span>
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
<span class="glyphicon form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<label for="captcha">验证码</label>
<span class="glyphicon glyphicon-refresh refresh" onClick="refreshCaptcha()"></span>
<span class="error-msg"></span>
<input type="text" maxlength="4" class="form-control captcha" id="captcha" name="captcha"
placeholder="验证码" >
<span class="glyphicon form-control-feedback captcha_icon"></span>
</div>
<!-- 注意表单中必须有type="submit"的按钮,否则表单验证通过后,无法进入回调函数submitHandler() -->
<button type="submit" class="btn btn-success login-btn">登 录</button>
<button type="button" class="btn btn-link to-register">还没有账号?去注册 >></button>
</form>
</div>
</div>
</div>
</div>
<script src="lib/jquery/jquery.min.js"></script>
<script src="lib/jquery/jquery.validation.min.js"></script>
<!-- 引入所有的Bootstrap的JS插件 -->
<script src="lib/bootstrap/js/bootstrap.min.js"></script>
<script src="js/login.js"></script>
</body>
</html>
login.css
次のCSSは比較的基本的なもので、主にWebフロントエンドの選択科目を勉強するときは、勉強はそれほど深くはなく、すべて基本的なものです。。とはいえ、なじみがないので、スタイルを調整する際にたくさんの穴を踏んでしまいました。
.clear-float {
clear: both;
}
.login-box {
/* border: 1px solid #000; */
padding: 0 16px;
border-radius: 8px;
margin-top: 100px;
box-shadow: 0 0 10px #ddd;
}
.photo {
/* 一定要设置为块状元素,否则margin auto不生效 */
display: block;
width: 100px;
height: 100px;
border: 1px solid #eee;
padding: 4px;
box-shadow: 0 0 10px #ddd;
background-color: #fff;
margin: 0 auto;
}
.login-btn {
width: 100%;
/* 设置line-height比设置height更好 */
line-height: 24px;
/* height: 24px; */
font-size: 17px;
margin: 8px 0;
}
.to-register {
float: right;
padding-right: 0;
}
.error-msg {
/* 不设置block,margin不起作用 */
display: block;
float: right;
color: #a94442;
font-weight: bold;
}
.captcha {
background-image: url(/account/captcha/generate);
background-repeat: no-repeat;
background-position: right;
/* 如果不加!important,就无法生效 */
padding-right: 120px !important;
}
.refresh {
margin-left: 4px;
cursor: pointer;
}
/* 复写.form-control的right属性,因为验证码输入框右端的提示图标遮挡住验证码 */
.captcha_icon {
/* 如果不加!important,就无法生效 */
right: 100px !important;
}
login.js(ハイライト)
// 点击刷新图标,刷新验证码
function refreshCaptcha() {
var url = '/account/captcha/generate?rand=' + Math.random();
$('#captcha').css({
'background-image': 'url(' + url + ')'
});
$('#captcha').val('');
var parentDiv = $('#captcha').parents('div.has-feedback');
var iconSpan = parentDiv.children('span.glyphicon');
var msgSpan = parentDiv.children('span.error-msg');
// 父亲div移除样式
parentDiv.removeClass('has-success has-error');
// 图标设置移除样式
iconSpan.removeClass('glyphicon-ok glyphicon-remove');
msgSpan.html('');
}
$(function() {
// 登录表单验证
$("#loginForm").validate({
// 表单验证成功通过后的回调
submitHandler: function(form) {
//console.log(form);
//form.submit();
// 异步提交表单
// Ajax提交数据
var email = $('#email').val();
var password = $('#password').val();
var captcha = $('#captcha').val();
$.ajax({
url: '/account/login', // 提交到controller的url路径
type: "POST", // 提交方式
data: {
email: email,
password: password,
captcha: captcha
},
dataType: "json", // 服务器端返回的数据类型
success: function (res) {
if (res.code === 2000) {
window.location.href = 'index.jsp';
} else {
alert('密码错误');
location.reload();
}
}
});
},
// 错误提示
errorPlacement: function(error, element) { // 错误信息,input表单项
// 找到父亲div
var parentDiv = element.parents('div.has-feedback');
// 找到显示msg的span
var msgSpan = parentDiv.children('span.error-msg');
// 找到图标的span
var iconSpan = parentDiv.children('span.glyphicon');
// 设置错误信息
msgSpan.html('').append(error);
// 父亲div添加样式has-error
parentDiv.addClass('has-error');
// 图标设置样式glyphicon-remove
iconSpan.addClass('glyphicon-remove');
},
// 成功时,移除
success: function(element) {
// 找到父亲div
var parentDiv = element.parents('div.has-feedback');
// 找到显示msg的span
var msgSpan = parentDiv.children('span.error-msg');
// 找到图标的span
var iconSpan = parentDiv.children('span.glyphicon');
// 设置错误信息
msgSpan.html('');
// 父亲div移除样式has-error,并添加样式has-success
parentDiv.removeClass('has-error');
parentDiv.addClass('has-success');
// 图标设置样式glyphicon-remove,并添加样式glyphicon-ok
iconSpan.removeClass('glyphicon-remove');
iconSpan.addClass('glyphicon-ok');
},
ignore: ".ignore",
// 表单验证规则
rules: {
email: { // input的name属性
required: true,
email: true,
//isMobile: true
remote: {
cache: false,
async: true,
type: 'GET',
url: '/account/photo',
data: { // 请求所需的参数列表
email: function() {
return $('#email').val();
}
},
// 由于remote需要的返回值是布尔值(false表示不通过),而实际返回值是一个封装对象
// 所以需要dataFilter对返回的封装对象进行预处理,并给remote返回所需的布尔值
dataFilter: function(jsonStr, type) {
var res = JSON.parse(jsonStr);
console.log(typeof(res));
console.log(res);
console.log(res.code);
var isOk = (res.code === 2000);
console.log(isOk);
// 如果email存在且data部分不为null(有头像),显示用户的头像
if (isOk && res.data != null) {
$('img.photo').attr('src', res.data);
}
return isOk;
}
}
},
password: {
required: true
},
captcha: {
required: true,
remote: {
cache: false,
async: true,
type: 'GET',
url: '/account/captcha/validate',
data: { // 提交给服务端的数据(键值对)
captcha: function() {
return $('#captcha').val();
}
},
dataFilter: function(jsonStr, type) {
var res = JSON.parse(jsonStr);
var isCorrect = (res.code === 2000);
if (!isCorrect) { // 验证码错误
refreshCaptcha();
}
return isCorrect;
}
}
}
},
messages: { // 与验证规则一一对应的消息提示
email: {
required: '邮箱不能为空',
email: '邮箱格式错误',
remote: '该邮箱尚未注册'
},
password: {
required: "密码不能为空"
},
captcha: {
required: "验证码不能为空",
remote: "验证码错误,已经刷新"
}
},
onkeyup: function(element, event) {
var name = $(element).attr("name");
if (name == "captcha") {
//不可去除,当是验证码输入必须失去焦点才可以验证(错误刷新验证码)
return false;
}
}
});
});