JavaScriptMVC之Fixture

注:阅读这篇同学必须已经认识了JavaScriptMVC,否则,看起来比较困难。

$.fixture(固定物)是拦截Ajax请求并且用一个文件或者函数来模拟响应结果。当你想开发没有后台的JavaScript,它是一个很好的技术支撑。

Fixtures的类型

一般我们使用Fixtures的2种方法。第一种方法是把Ajax请求映射到一个文件。Fixtures会拦截/tasks.json请求,且把这些请求指向fixtures/tasks.json文件。

$.fixture("/tasks.json","fixtures/tasks.json");

第二种方法是把Ajax请求映射到一个函数。Fixtures会拦截/tasks/ID.json请求,且更新数据。

$.fixture("PUT/tasks/{id}.json",function(original,settings,headers){

return{updatedAt:newDate().getTime()}

})

我们还可以把Fixtures归类为2个类型:

1、静态-响应是一个文件

2、动态-响应是靠函数生成

查找静态和动态的Fixture是方式是不同的。

静态Fixtures

静态Fixtures使用替换不同URL来响应Ajax的请求。

//looksinfixtures/tasks1.jsonrelativetopage

$.fixture("tasks/1","fixtures/task1.json");

$.fixture("tasks/1","//fixtures/task1.json");

动态Fixtures

动态Fixtures能获取Ajax请求且模拟服务端返回结果。

例如,从服务端返回一个成功响应的JSON数据。

$.fixture("/foobar.json",function(orig,settings,headers){

return[200,"success",{json:{foo:"bar"}},{}]

})

这个Fixture函数可以使用符号表明:

function(originalOptions,options,headers){

return[status,statusText,responses,responseHeaders]

}

当这个Fixture函数被调用用了以下参数:

originalOptions-默认的Ajax设置项

options-请求设置项

headers-请求头

且把参数以数组的格式返回:

status-HTTP响应状态

statusText-HTTP响应状态文本

responses-HTTP响应结果

headers-响应包头

然而,$.fixture处理一般的例子都是你需要一个成功响应的JSON数据。这个和之前的写法是相似的:

$.fixture("/foobar.json",function(orig,settings,headers){

return{foo:"bar"};

})

如果你想返回一个数组数据,你可以在响应的数组中再加上其它数组。

$.fixture("/tasks.json",function(orig,settings,headers){

return[["first","second","third"]];

})

$.fixture功能原理相似于Jquery的Ajax运作系统。想创建更好的Fixtures,理解它是一个关键。

模板匹配Urls

常常,你想一个动态的Fixture通过Urls处理多个资源(例如一个RestUrl)。$.fixture模板匹配Urls允许你用一个通配符去匹配Urls。下面的例子模拟获取和修改100个todos的服务。

//createtodos

vartodos={};

for(vari=0;i<100;i++){

todos[i]={

id:i,

name:"Todo"+i

}

}

$.fixture("GET/todos/{id}",function(orig){

//returntheJSONdata

//noticethatidispulledfromtheurlandaddedtodata

returntodos[orig.data.id]

})

$.fixture("PUT/todos/{id}",function(orig){

//updatethetodo'sdata

$.extend(todos[orig.data.id],orig.data);

//returndata

return{};

})

注意那数据是通过模板匹配Urls(ex:{id})添加到原始数据对象中。

模拟错误

下面是模拟一个未经授权请求到/foo

$.fixture("/foo",function(){

return[401,"{type:'unauthorized'}"]

});

通过以下请求可以收到下面内容。

$.ajax({

url:'/foo',

error:function(jqXhr,status,statusText){

//status==='error'

//statusText==="{type:'unauthorized'}"

}

})

关闭Fixtures

你可以删除一个通过把Fixture的选项设置为null。

//addafixture$.fixture("GETtodos.json","//fixtures/todos.json");

//removethefixture$.fixture("GETtodos.json",null)//关闭特定的fixture

你还可以设置[jQuery.fixture.on$.fixture.on]的值为false:

$.fixture.on=false;//关闭所有fixture

现在我们来重点讲解$.fixture.make,

$.fixture.make可以创建一个CRUD服务层,它还支持条件查询,排序,分组,过滤等等,

从这句话,我们就可以看到make是多强大,几乎包含了页面与后台交互的绝大部分操作。

就连Ajax超时的情况fixture也给我们考虑到了,使用$.fixture.delay来达到。

注意:在条件查询中,fixture要求我们查询的参数名称中必须包含Id或者_id,否则,查询条件不起作用。

有些同学如果使用了查询可能会发现说,只是提供了精确的查询,如果想要模糊查询怎么办?

fixture有没有提供这个功能呢,看看源代码,发现没有,但是我们又看到make最后一个参数是一个过滤器,我们是不是可以通过这个来实现呢。

实践证明,这是可以的,只是需要自己去实现这个过滤器。说到这,我们平时使用到的请求类型都几乎包含了,

大家看看有没有其它请求没有,可以提出来,大家研究研究,看看怎么去实现它。

有了这个Fixture,我们开发人员就可以使用JavaScriptMVC+WebUIPlugin来开发Web项目的高保真了,而且是比较真实的demo。

让我们一起来完成演示例子,以后,我们就可以根据这个例子来构造自己项目的Fixtures。

下面让我一步一步讲解如何在项目到构造和使用Fixtures。

创建项目

在这里,我把下载的MVC包放到本地的E:\jQuery\javascriptmvc这个目录,使用DOC命令,进入到E:\jQuery\javascriptmvc这个目录下,

执行jsjquery/generate/appcookbook命令,生成工程,

执行命令后,我们在E:\jQuery\javascriptmvc目录下看到生成的cookbook文件夹,这就是我们创建的工程,然后我们再在这个工程下面创建一个模块message,执行命令:jsjquery/generate/scaffoldCookbook.Models.Message,

我们打开cookbook文件夹,看到文件夹下面有一个message文件夹,

这就是我们生成的message模块,而且我们还看到一个fixtures文件夹,我们写的fixture就是在这个文件夹下的fixtures.js文件。

接着修改cookbook.html,如下:

<!DOCTYPEHTML>

<htmllang="en">

<head>

<title>cookbook</title>

</head>

<body>

<body>

//把多余的代码删除,添加下面2条代码

<ulid='messages'></ul>//显示message列表的元素

<formid='create'action=''></form>//创建message使用到的元素

<scripttype='text/javascript'

src='../steal/steal.js?cookbook'>

</script>

</body>

</body>

</html>

接着打开cookbook.html,我们可以看到生成的代码已经具有删除,创建,显示所有message的功能。

但是没有以下功能:修改,条件精确查询,条件模糊查询,分组,排序等。

修改:

其实修改功能已经存在,只是页面上没有体现出来,现在我们给页面上添加上修改的功能。

修改E:\jQuery\javascriptmvc\cookbook\message\list\views\message.ejs文件,添加修改功能的触发元素源。最终代码如下:

<h3><%=name%><ahref='javascript://'class='destroy'>X</a>

<ahref='javascript://'class='update'>U</a>//这句是我们添加的代码,点击它可以起到修改的功能

</h3>

<p><%=description%></p>

接着我们来修改controller:E:\jQuery\javascriptmvc\cookbook\message\list\list.js文件,最终代码如下:

steal('jquery/controller',

'jquery/view/ejs',

'jquery/controller/view',

'cookbook/models')

.then('./views/init.ejs',

'./views/message.ejs',

function($){

/**

*@classCookbook.Message.List

*@parentindex

*@inheritsjQuery.Controller

*Listsmessagesandletsyoudestroythem.

*/

$.Controller('Cookbook.Message.List',

/**@Static*/

{

defaults:{}

},

/**@Prototype*/

{

init:function(){

//这句就是我们后续需要添加查询功能的语句,我们会不段修改这句来达到各种查询的效果

this.element.html(this.view('init',Cookbook.Models.Message.findAll()))

},

'.destroyclick':function(el){

if(confirm("Areyousureyouwanttodestroy?")){

el.closest('.message').model().destroy();

}

},

//这个是我们添加的触发修改功能的函数,我们把这个记录的name的值修改为test

'.updateclick':function(el){

el.closest('.message').model().update({name:'test'});

},

"{Cookbook.Models.Message}destroyed":function(Message,ev,message){

message.elements(this.element).remove();

},

"{Cookbook.Models.Message}created":function(Message,ev,message){

this.element.append(this.view('init',[message]))

},

"{Cookbook.Models.Message}updated":function(Message,ev,message){

message.elements(this.element)

.html(this.view('message',message));

}

});

});

条件精确查询:

修改E:\jQuery\javascriptmvc\cookbook\models\message.js文件,最终代码如下:

steal('jquery/model',function(){

/**

*@classCookbook.Models.Message

*@parentindex

*@inheritsjQuery.Model

*Wrapsbackendmessageservices.

*/

$.Model('Cookbook.Models.Message',

/*@Static*/

{

/**

*代码修改点

*/

findAll:function(attr,success,error){

return$.ajax({

url:'messages',

type:'get',

dataType:'jsonmessage.models',//这句message.models很重要,因为这个是把影响回来的数据model化

success:success,

error:error,

data:attr,

fixture:'-messages'//指定ajax发送到fixture的messages中

});

},

findOne:"/messages/{id}.json",

create:"/messages.json",

update:"/messages/{id}.json",

destroy:"/messages/{id}.json"

},

/*@Prototype*/

{});

})

用浏览器打开cookbook.html,突然发现之前一起显示的列表,现在没有了,看看浏览器的日志,我们看到nofixturefound。说明上面的messages没有找到。

现在就到我们修改fixtures.js文件的时候了,最终代码如下:

//mapfixturesforthisapplication

steal("jquery/dom/fixture",function(){

$.fixture.make(["messages","message"],10,function(i,messages){

vardescriptions=["grillfish","makeice","cutonions"]

return{

name:"message"+i,

msg_id:'msg_'+i,//精确查询功能

msgId:'msg'+i,//精确查询功能

description:$.fixture.rand(descriptions,1)[0]

}

}

})

我们可以通过msg_id或者msgId来精确查询记录,有没有发现一个很奇怪的现象就是这些可以精确查询字段都是_id或者Id才可以。

原来,fixture提供的精确查询条件字段一定要包含_id或者Id,否则,不能查询,像上面的name,description都不可以,除非我们修改fixture中的源码。

接着修改list.js文件中的这句代码:

//这句就是我们后续需要添加查询功能的语句,我们会不段修改这句来达到各种查询的效果

this.element.html(this.view('init',Cookbook.Models.Message.findAll()))

修改成如下:

this.element.html(this.view('init',Cookbook.Models.Message.findAll({

msg_id:'msg_1'

})))

当然我们还可以添加msgId这个查询条件。

在这里我们还需要提到的一个就是fixture默认提供的一个分页查询参数,offset(从那条记录起)和limit(第页记录数)。修改上面代码如下:

this.element.html(this.view('init',Cookbook.Models.Message.findAll({

offset:0,

limit:5

})));

我们可以看到10记录,只显示了5条,这个就是分页的模拟结果了。

排序,分组功能:

这2个功能相似,所以放到一起讲,因为它们所达到的效果其实差不多。fixture提供2个查询参数来达到,order和group。

我们修改查询代码(list.js),代码如下:

this.element.html(this.view('init',Cookbook.Models.Message.findAll({

order:["descriptionasc"]

})))

看看效果,再修改这个代码如下:

this.element.html(this.view('init',Cookbook.Models.Message.findAll({

group:["description"]

})))

看看效果,是不是和上面的差不多。

条件模糊查询:

我们只需要修改fixture.js就可以达到这个效果,查看fixture的API,我们看到$.fixture.make最后面的一个参数是一个过滤函数,我们就拿这个函数

来完成模糊查询的功能,修改代码如下:

//mapfixturesforthisapplication

steal("jquery/dom/fixture",function(){

$.fixture.make(["messages","message"],10,function(i,messages){

vardescriptions=["grillfish","makeice","cutonions"]

return{

name:"message"+i,

msg_id:'msg_'+i,//精确查询功能

msgId:'msg'+i,//精确查询功能

description:$.fixture.rand(descriptions,1)[0]

}

},

/**

*过滤器,完成模糊查询功能

*模糊查询description字段中包含make文本的记录

*/

function(item,settings){

if(item.description.indexOf(settings.data.description)>-1){

returnitem;

}

}

)

})

再次修改查询条件(list.js),代码如下:

this.element.html(this.view('init',Cookbook.Models.Message.findAll({

description:'make'

})));

我们就记记录集中的make模糊查询出来。

至此,我们所需要讲的使用fixture来模拟我们所需要的Ajax请求和影响已经讲完。

相关推荐