您的位置:首页 > Web前端 > JavaScript

基于Backbone.js的JavaScript MVC示例程序(9)

2012-08-21 19:42 417 查看
一.概述

二.REST Server的实现

2.1 REST API设计

2.2 数据库设计

2.3 用MyBatis实现的DAO层

2.4 用Jersey实现的REST API

2.5 用Spring AOP实现的日志功能

三.前端的实现

3.1 显示User列表

3.2 显示User详细信息

3.3 修改User信息

3.4 增加User

3.5 删除User

3.6 添加validate

3.6 添加validate

使用 JavaScript 实现表单的验证是一个很常见的问题,jQuery 有不少表单验证的插件,只需要经过简单的配置就能完成验证的功能。

因为是初学 JavaScript,所以先自己用 jQuery 写了一个表单验证的例子,然后讨论一下怎样将 jQuery 的表单验证用到 Backbone.js 构建的程序中,最后使用 Backbone.Model 的 validate() 方法来实现验证的过程。

3.6.1 使用 jQuery 实现的表单验证

表单只有四个 input,界面如图所示:



各字段的验证规则如下:



6.1.html 表单相关的 HTML 代码如下,因为想熟悉一下 jQuery 选择器的使用,所以 HTML 中没有使用任何的 id/class:

<form action="#" method="post">
<p>
<label for="username">Username:</label>
<input type="text" name="username" />
</p>
<p>
<label for="password">Password:</label>
<input type="text" name="password" />
</p>
<p>
<label for="re-password">Re-password:</label>
<input type="text" name="re-password" />
</p>
<p>
<label for="email">Email:</label>
<input type="text" name="email" />
</p>
<p><input type="submit" value="Register" /></p>
</form>


jquery-validate-1.js 的源码如下,关键的地方已经给出注释:

$(document).ready(function(){

//光标移动到username的input时触发,如果已经有错误/正确提示则不改变提示,如果没有提示输入
$("input[name='username']").focus(function(){
if ($("input[name='username']+span.error").size() == 0
&& $("input[name='username']+span.success").size() == 0) {
$(this).after("<span class='hint'>Please enter your username.</span>");
}
});
//光标移出username的input时触发
$("input[name='username']").blur(function(){
$("input[name='username']+span").remove(); //去掉之前的提示
if($(this).val().length < 6 || $(this).val().length>12){ //判断长度,给出提示
$(this).after("<span class='error'>Username contains 6-12 characters.</span>");
}else{ //向服务器发出AJAX请求,判断username是否已经存在,给出提示
$.ajax({
url:"./rest/user/validate/"+$(this).val(),
success:function(data, textStatus){
if(data == "true"){
$("input[name='username']").after("<span class='success'>Passed.</span>");
}else{
$("input[name='username']").after("<span class='error'>Username has been used.</span>");
}
}
});
}
});

$("input[name='password']").focus(function(){
if ($("input[name='password']+span.error").size() == 0
&& $("input[name='password']+span.success").size() == 0) {
$(this).after("<span class='hint'>Please enter password again.</span>");
}
});
$("input[name='password']").blur(function(){
$("input[name='password']+span").remove();
if($(this).val().length < 6 || $(this).val().length>12){
$(this).after("<span class='error'>Password contains 6-12 characters.</span>");
}else{
$(this).after("<span class='success'>Passed.</span>");
}
});

$("input[name='re-password']").focus(function(){
if ($("input[name='re-password']+span.error").size() == 0
&& $("input[name='re-password']+span.success").size() == 0 ) {
$(this).after("<span class='hint'>Please enter your password again.</span>");
}
});
$("input[name='re-password']").blur(function(){
$("input[name='re-password']+span").remove();
if($(this).val() ==""){
$(this).after("<span class='error'>Please enter your password again.</span>");
}else if($(this).val() != $("input[name='password']").val()){ //判断两次输入的password是否相同
$(this).after("<span class='error'>Two passwords are not same.</span>");
}else{
$(this).after("<span class='success'>Passed.</span>");
}
});

$("input[name='email']").focus(function(){
if ($("input[name='email']+span.error").size() == 0
&& $("input[name='email']+span.success").size() == 0 ) {
$(this).after("<span class='hint'>Please enter your email.</span>");
}
});
$("input[name='email']").blur(function(){
$("input[name='email']+span").remove();
if(!$(this).val().match(/^\w{3,}@\w+(\.\w+)+$/)){ //正则表达式判断email格式是否正确
$(this).after("<span class='error'>Invalid email format.</span>");
}else{
$(this).after("<span class='success'>Passed.</span>");
}
});

//表单提交的时候触发所有input的blur事件,如果没有error才能提交表单
$("form").submit(function(){
$("input").blur();
if ($("form span.error").size() > 0) {
return false;
}
});

});


注意看78-83行,表单提交的事件(submit)发生时手动触发了所有 input 的 blur 事件,如果没有 error 才能提交表单。这样可以避免没有填写某个 input,而导致它的 blur 事件没有触发,并没有进行正确的验证。

写这个例子时也遇到了一些问题,在解决问题的过程中学到了不少,对 jQuery 的选择器、AJAX请求、页面操作等等都更熟悉了。

3.6.2 将 jQuery 的表单验证用到 Backbone.js 的程序中

上面 jQuery 的表单验证是在我学习 Backbone.js 之前写的,因此和我们的这个示例程序不太一样,我们之前写的 Backbone.js 程序中没有表单,少了 re-password,多了 phone,也懒得再改了,直接拿过来用吧,反正关键问题是如何整合起来使用。

我们简单地将 jquery-validate-1.js 引入到 5.html 文件中,测试发现根本不起作用。原因是 jquery-validate-1.js 中使用的是最常见的绑定事件的方法,只能将事件绑定到 $(document).ready() 执行的时候已经存在的页面元素上,而我们的所有 input 都是后来由 Backbone.js 显示出来的,所以绑定不上。

jQuery 中对事件的绑定有 bind() live() delegate() 三种方法,三者的区别看这里:http://kb.cnblogs.com/page/94469/。简单地来说 bind() 将事件绑定到特定的 DOM 元素上,加载的时候不存在就绑不上;live() 将事件绑定到 $(document) 元素上,事件发生的时候动态地去搜索符合要求的 DOM 元素;delegate() 将事件绑定到某个 DOM 元素上,事件发生的时候动态地去它的所有子元素里面搜索符合要求的 DOM 元素。因此我们使用 delegate() 改编一下 jquery-validate-1.js。

例如,在jquery-validate-1.js 中

$("input[name='username']").focus(function(){...});


改为 jquery-validate-2.js 中的:

$("#right").delegate("input[name='username']","focus",function(){...});


其他 input 相关的事件也这么修改一下就行了,测试之后发现对 input 的验证都可以正常使用了。

但是我们的程序中没有表单,因此也不会触发 submit 事件,只需要将 submit 事件上绑定的的内容移到 UserInfoView.submitEdit() UserListView.submitUserForm() 中,在 model 向服务器端 sync 之前判断有没有 error,如果有 error 就阻止 sync 的执行。mvc6.2.js 代码如下所示:

var UserInfoView = Backbone.View.extend({
submitEdit : function() { //修改
$("input").blur();
if ($("span.error").size() > 0) {
return;
}
this.model.save({
"username":$("input[name='username']").val(),
"password":$("input[name='password']").val(),
"email":$("input[name='email']").val(),
"phone":$("input[name='phone']").val(),
});
this.$("#user-info").removeClass("editing");
},
...//其余不变
});

var UserListView = Backbone.View.extend({
submitUserForm : function() { //修改
$("input").blur();
if ($("span.error").size() > 0) {
return;
}
var user  = new User({
"username":$("input[name='username']").val(),
"password":$("input[name='password']").val(),
"email":$("input[name='email']").val(),
"phone":$("input[name='phone']").val(),
});

this.userList.create(user,{wait:true});
$("input[name='username']").val(""),
$("input[name='password']").val(""),
$("input[name='email']").val(""),
$("input[name='phone']").val(""),
alert("Add a user!");
},
...//其余不变
});


还有一个方法就是将这部分内容移到 Backbone.Model 的 validate() 方法中去,也就是说还可以这么修改:

var User = Backbone.Model.extend({
validate : function(attrs) { //新增
$("input").blur();
if ($("span.error").size() > 0) {
return "hahaha"; //随便返回什么,触发error事件就能阻止sync的发生了
}
}
});


上面两个解决方法选一个就行了。关于 validate() 方法的详解请看下一小节。

3.6.3 使用 Backbone.Model 的 validate() 实现验证

首先来看一下官网对 validate() 的说明:

model.validate(attributes)
该方法是未定义的,如果有在Javascript执行的需要,建议用自定义的验证逻辑重载它。 validate 会在 set 和 save 之前调用,并传入待更新的属性。 如果模型和属性通过验证,不返回任何值; 如果属性不合法,返回一个可选择的错误。该错误可以是简单的用于显示的字符串错误信息, 或者是一个可以描述错误详细的 error 对象。 如果 validate 返回错误,set 和 save 将不会执行。 失败的验证会触发一个 "error" 事件。

所以说 validate() 只能对 model 的所有属性整体做一次验证,然后返回错误信息,不能像 jQuery 那样在填完每一个 input 之后都进行验证。

Model 里面虽然没有定义 validate() 方法,但是有个 _validate() 方法,会在 Model.set()、Model.save()、Collection.create() 中被调用,_validate() 的源码如下:

// Run validation against the next complete set of model attributes, returning `true` if all is well. If a specific `error` callback has been passed, call that instead of firing the general `"error"` event.
_validate: function(attrs, options) {
if (options.silent || !this.validate) return true;
attrs = _.extend({}, this.attributes, attrs);
var error = this.validate(attrs, options);
if (!error) return true;
if (options && options.error) {
options.error(this, error, options);
} else {
this.trigger('error', this, error, options);
}
return false;
}


可以看出来,如果 validate() 有返回值,那么就会触发 error 事件(10行),并且有 this、error、options 三个参数,我们可以根据第二个参数来输出错误信息。

首先在 6.3.html 的表单中加入显示错误信息的部分:

<!-- 增加显示错误信息的位置  -->
<script type="text/template" id="user-info-template">
<h3>User Information</h3>
<button id="edit">Edit</button>
<p class="error"></p>
<ul id="user-info">
<li>ID:<span><%= id %></span></li>
<li>Username:<span><%= username %></span><input type="text" name="username" value="<%= username %>" /></li>
<li>Password:<span><%= password %></span><input type="password" name="password" value="<%= password %>" /></li>
<li>Email:<span><%= email %></span><input type="text" name="email" value="<%= email %>" /></li>
<li>Phone:<span><%= phone %></span><input type="text" name="phone" value="<%= phone %>" /></li>
<button id="edit-submit">Submit</button>
</ul>
</script>
<!-- 增加显示错误信息的位置  -->
<script type="text/template" id="user-form-template">
<h3>Add User</h3>
<p class="error"></p>
<ul id="user-form" class="editing">
<li>Username:<input type="text" name="username" /></li>
<li>Password:<input type="password" name="password" /></li>
<li>Email:<input type="text" name="email" /></li>
<li>Phone:<input type="text" name="phone" /></li>
<button id="add-submit">Submit</button>
</ul>
</script>


然后对 mvc6.3.js 进行修改,在 User 中加入 validate() 方法,在 UserInfoView.submitEdit()、UserListView.submitUserForm() 中加入对错误信息的显示:

$(document).ready(function() {

var User = Backbone.Model.extend({
validate : function(attrs) { //新增,验证属性是否合法
if (attrs.username.length<6 || attrs.username.length>12) {
return "Username contains 6-12 characters.";
}
var obj = $.ajax({
url : "./rest/user/validate/" + attrs.username,
async : false,
});
if (obj.responseText == "false") {
return "Username has been used.";
}
if (attrs.password.length<6 || attrs.password.length>12) {
return "Password contains 6-12 characters.";
}
if (attrs.email.length == 0) {
return "Please enter your email.";
}
if(!attrs.email.match(/^\w{3,}@\w+(\.\w+)+$/)){
return "Invalid email format.";
}
},
});

var UserInfoView = Backbone.View.extend({
submitEdit : function() { //修改
var m = this.model;
this.model.save({
"username":$("input[name='username']").val(),
"password":$("input[name='password']").val(),
"email":$("input[name='email']").val(),
"phone":$("input[name='phone']").val(),
},
{
error : function(m,error) {  //显示错误信息
$(".error").html(error);
},
success : function() {
$("#user-info").removeClass("editing");
}
});
},
... //其余不变
});

var UserListView = Backbone.View.extend({
submitUserForm : function() {
var user  = new User({
"username":$("input[name='username']").val(),
"password":$("input[name='password']").val(),
"email":$("input[name='email']").val(),
"phone":$("input[name='phone']").val(),
});
var m = this.model; //修改
this.userList.create(user,{
wait : true,
error : function(m,error) { //显示错误信息
$(".error").html(error);
},
success : function() {
$("input[name='username']").val(""),
$("input[name='password']").val(""),
$("input[name='email']").val(""),
$("input[name='phone']").val(""),
alert("Add a user!");
}
});
},
... //其余不变
});
... //其余不变
});


完成之后的界面如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: