常常,项目中创建,修改数据时,都会对前台提交的数据验证,转变。然后再提交给后台处理,这个步骤 是我们开发人员一定要完成的工作。在之前,我们在做数据验证或者转变时,都是把各种验证和数据转变都 写成各种函数放在工具文件中,让整个项目需要的地方调用。
那我们如果使用JavaScriptMVC开发Web项目时,也可以这样验证吗?答案是肯定的。但是,如果我们按之前 的方法来完成验证和转变,那真的是浪费了MVC框架了,它让我们写的验证和数据转变不现写在控制层,而是 把它放在了数据层,这样是不是更符合对象编程规范呢,而且阅读和维护起来更加方便快捷。
好了,讲了JavaScriptMVC的数据验证和转变的好处,下面让我们来一起学习在JavaScriptMVC中如何验证和转变 数据。
首先,我们来讲解我们最常用的验证,不管我们在那个项目都会完成这个工作,对于各种验证手法,想念大家都 也已经了解,在这里我不会大量的举例各种验证,我只是把JavaScriptMVC中它提供了那些工具,让我们更加方便 编写验证代码,而且全部满足我们平常的需求。
那JavaScriptMVC是自带验证功能的呢,查看了API,原来验证功能是JavaScriptMVC的
Model下面的一个模块validations, 就是它帮我们完成了一些常用的验证,而且还保留了给用户自定义验证的接口。 那Validations提供了那些常用验证函数,又是如何给用户提供自定义验证的接口呢?下面我们一一列出。
/** * 函数 validateFormatOf * * 验证属性值是否符合正则表达式 * @param {Array|String} 属性或者属性组 * @param {RegExp} 验证的正则表达式 * @param {Object} 可选项,这里只提供2个特殊标识,message:自己错误信息,testIf:是否执行验证函数,返回true则执行,false,不执行 * 例如:validateFormatOf(["name"],/(d+)/,{message:'不符合表达式',testIf:function(){return false;}}); */ /** * 函数 validateInclusionOf * * 难属性值是否在给出的验证数组内 * @param {Array|String} 属性或者属性组 * @param {Array} 验证包含的数组 * @param {Object} 可选项,这里只提供2个特殊标识,message:自己错误信息,testIf:是否执行验证函数,返回true则执行,false,不执行 * 例如:validateInclusionOf(["name"],["lisi","test"],{message:'不在所给文本内',testIf:function(){return false;}}); * * 判断属性name的内容是否是lisi或者test,如果是,则返回正确,否则,返回错误信息 * */ /** * 函数 validateLengthOf * * 判断属性值文本的长度是否在给出的范围内 * @param {Array|String} 属性或者属性组 * @param {Number} 属性值文本最小长度 * @param {Number} 属性值文本最小长度 * @param {Object} 可选项,这里只提供2个特殊标识,message:自己错误信息,testIf:是否执行验证函数,返回true则执行,false,不执行 * 例如:validateLengthOf(["name"],2,5,{message:'文本长度大于5或者小于2',testIf:function(){return false;}}); * */ /** * 函数 validatePresenceOf * * 属性值是否为空判断 * Validates that the specified attributes are not blank. See [jquery.model.validations validation] for more on validations. * @param 属性或者属性组 * @param {Object} 可选项,这里只提供2个特殊标识,message:自己错误信息,testIf:是否执行验证函数,返回true则执行,false,不执行 * 例如:validatePresenceOf(["name"],{message:'文本为空',testIf:function(){return false;}}); * */ /** * 函数 validateRangeOf * * 属性值大小是否在范围内 * @param {Array|String} 属性或者属性组 * @param {Number} 数值最小值 * @param {Number} 数值最大值 * @param {Object} 可选项,这里只提供2个特殊标识,message:自己错误信息,testIf:是否执行验证函数,返回true则执行,false,不执行 * 例如:validatePresenceOf(["name"],2,5,{message:'数值小于2或者大于5',testIf:function(){return false;}}); * * */
以下是Validations提供5个常用验证函数,它们都是静态方法,可以在Model中直接调用 说完上面5个函数,我们发现怎么错误信息都是英文的,而且很简单,那能不能替换成自己的错误信息呢?
当然能,而且Validations提供了2种方式替换成自己的错误信息。
最直接一种就就是修改Validations这个属性:
validationMessages :{
format:"is invalid",
inclusion:"is not a valid option(perhaps out of range)",
lengthShort:"is too short",
lengthLong:"is too long",
presence:"can't be empty",
range:"is out of range";
}
上面这些信息就是5个函数提供的信息,我们可以替换成自己的错误信息。
另外一种就是在函数最后一个参数里传递我们自定义的错误信息。例如: this.validateLengthOf("description",2,5,{message:'自定义的错误信息';});至此,5个函数就讲完。
另外一种就是在函数最后一个参数里传递我们自定义的错误信息。例如: this.validateLengthOf("description",2,5,{message:'自定义的错误信息';});至此,5个函数就讲完。
最后一个就是给用户留下的自定义验证接口,当然我们也可以自己写自定义去完成上面5个函数的功能。
其实在我们很多项目中,用到最多的应该是这个函数,因为实际情况比较复杂,所以大多数都需要我们自己定义验证和返回自定义的错误信息。
最后我们看看Validations还给我们提供了一个跳过验证的选项,我们有时候测试的时候不想用到验证,但是我们又已经写了验证,是不是删除掉,然后要用的时候再加回来呢? 在这里完成不会,我们直接使用Validations提供的
一个选项testIf就可以达到这个目的,例如:
this.validateInclusionOf("date", ['test', 'aaaa'], { testIf : function() { return false;// 返回false,不对date验证,如果返回true,则验证; } });
下面让我们让例子来实践:
//模型代码:
$.Model("Contact", { init : function() { this.validate("birthday", function() { if (this.birthday == null) { return "your birthday needs to be formatted YYYY-MM-DD"; } if (this.birthday > new Date) { return "your birthday needs to be in the past"; } }); this.validateLengthOf("description", 2, 5, { message : '自定义的错误信息 ' }); this.validateInclusionOf("date", ['test', 'aaa'], { testIf : function() { return false; } }); }, attributes : { birthday : 'date', name : 'string' }, findAll : "/contacts.json", update : "/contacts/{id;}.json" }, { ageThisYear : function() { return new Date().getFullYear() - this.birthday.getFullYear(); }, getBirthday : function() { return "" + this.birthday.getFullYear() + "-" + (this.birthday.getMonth() + 1) + "-" + this.birthday.getDate(); } });
//控制器代码
$.Controller('Msgmanage.Message.Create', { init : function() { this.element.html(this.view()); }, submit : function(el, ev) { ev.preventDefault(); this.element.find('[type=submit]').val('Creating...'); var model = new Msgmanage.Models.Message(el.formParams()); // 打印验证错误信息 console.info(model.errors()); }, saved : function() { this.element.find('[type=submit]').val('Submit'); this.element[0].reset(); } });
数据格式转换(convert)
所谓数据格式转换,就是把同一个数据转换成不同的格式。
例如:日期的格式,有时候我们前台显示的日期格式是2010-12-12,但是后台响应给我们的格式是2012:12:12。这样就需要我们在显示数据之前,把数据转换过来。
在JavaScriptMVC中提供了2种方式:Setter和Convert。虽然2种方式,但是其它他们的作用域是不一样的,如果是一个很特殊的字段需要转换成一个很特殊的格式,那本人觉得使用Setter比较好,但是如果是一种类型的数据格式那使用Convert方式会更合理。
下面让我们介绍Setter:
// A contact model $.Model("Contact", { findAll : "/contacts.json" }, { // 我们可以通过模型中的setter,转换出生日期的格式,我们可以看到, //使用Setter,只是在一个地方可以使用,不能给其它字段共用 setBirthday : function(raw) { if (typeof raw == 'string') { var matches = raw.match(/(\d+)-(\d+)-(\d+)/) return new Date(matches[1], (+matches[2]) - 1, matches[3]) } else if (raw instanceof Date) { return raw; } } });
Convert:
$.Model("Contact", { attributes : { birthday : 'date' }, convert : { // 使用convert,我们主要在属性里指定birthday的数据类型为date, //那么就是会调用到这个转换函数,如果其它字段也日期类型,那么,我们指定数据为date即可, // 从这里我们就可以看到,这个是可以公用的,但是我们也看到它的局限性, //它只能给这个模型使用,如果其它模型也想定义日期类型,是不是又得复制过去呢 // 这样的作法明显不好,所以,我们还是回到正常的写法,把这个函数自定到工具类中, //然后在convert中调用,这样,我们就可以使用同一份代码了 date : function(raw) { if (typeof raw == 'string') { var matches = raw.match(/(\d+)-(\d+)-(\d+)/) return new Date(matches[1], (+matches[2]) - 1, matches[3]) } else if (raw instanceof Date) { return raw; } } } }, {// No prototype properties necessary })
最终的代码,定义一个工具类:
$.Class("Util", { valDate : function(raw) { if (typeof raw == 'string') { var matches = raw.match(/(\d+)-(\d+)-(\d+)/) return new Date(matches[1], (+matches[2]) - 1, matches[3]) } else if (raw instanceof Date) { return raw; } } }, {});
再在模型中调用这个工具的函数:
$.Model("Contact", { attributes : { birthday : 'date' }, convert : { date : function(raw) { return Util.valDate(raw); } } }, { // No prototype properties necessary })
至此,我们讲解数据处理就先讲到这里了。