如何保存Backbone.js模型数据?

tes*_*dtv 86 javascript json javascript-framework backbone.js

我更喜欢前端开发,最近开始在我的应用程序中探索Backbone.js.我想将模型数据保存到服务器.

能否请您解释保存模型数据的各种方法(使用json格式).我在服务器端使用Java.此外,我主要看到REST用于保存数据.由于我更喜欢​​前端开发,我不知道REST和其他类似的东西.

如果有人能用一些简单的例子向我解释这个过程,那就太好了.

jmk*_*142 271

基本上,模型具有称为属性的属性,属性是特定模型可能具有的各种值.Backbone使用JSON对象作为使用采用JSON对象的各种方法填充这些值的简单方法.例:

Donuts = Backbone.Model.extend({
    defaults: {
        flavor: 'Boston Cream',  // Some string
        price: '0.50'  // Dollars
    }
});
Run Code Online (Sandbox Code Playgroud)

要填充模型,有几种方法可以实现.例如,您可以通过传入名为set()的JSON OR use方法来设置模型实例,该方法接受属性的JSON对象.

myDonut = new Donut({'flavor':'lemon', 'price':'0.75'});
mySecondHelping = new Donut();
mySecondHelping.set({'flavor':'plain', 'price':'0.25'});

console.log(myDonut.toJSON());
// {'flavor':'lemon', 'price':'0.75'}
console.log(mySecondHelping.toJSON());
// {'flavor':'plain', 'price':'0.25'}
Run Code Online (Sandbox Code Playgroud)

因此,这使我们能够保存模型并将它们保存到服务器中.有关"什么是REST/RESTful?"的大量详细信息.并且很难在这里简短地解释所有这些.特别是在REST和Backbone保存方面,要解决的问题是HTTP请求的语义以及您对数据的处理方式.

您可能习惯了两种HTTP请求.GET和POST.在RESTful环境中,这些动词对于Backbone假定的特定用途具有特殊含义.当您想从服务器获取某个资源时(例如我上次保存的甜甜圈模型,博客条目,计算机规范)并且该资源存在,您执行GET请求.相反,当您要创建新资源时,请使用POST.

在进入Backbone之前,我从未触及过以下两种HTTP请求方法.PUT和DELETE.这两个动词对Backbone也有特定的含义.当您想要更新资源时(例如,将柠檬甜甜圈的味道改为柠檬甜甜圈等),您可以使用PUT请求.如果要同时从服务器中删除该模型,请使用DELETE请求.

这些基础知识非常重要,因为使用RESTful应用程序,您可能会有一个URI指定,它将根据您使用的请求动词的类型执行相应的任务.例如:

// The URI pattern
http://localhost:8888/donut/:id

// My URI call
http://localhost:8888/donut/17
Run Code Online (Sandbox Code Playgroud)

如果我对该URI进行GET,它将获得ID为17的甜甜圈模型.:id取决于您如何保存服务器端.这可能只是数据库表中的甜甜圈资源的ID.

如果我用新数据对该URI进行PUT,我会更新它,保存它.如果我删除该URI,那么它将从我的系统中清除它.

使用POST,由于您尚未创建资源,因此它将没有已建立的资源ID.也许我想要创建资源的URI目标就是:

http://localhost:8888/donut
Run Code Online (Sandbox Code Playgroud)

URI中没有ID片段.所有这些URI设计都取决于您以及您对资源的看法.但是关于RESTful设计,我的理解是你希望将你的动作的动词保存到你的HTTP请求中,并将资源作为名词,使URI易于阅读和人性化.

你还在听我说吗?:-)

让我们回过头来思考Backbone.Backbone很棒,因为它为你做了很多工作.为了节省我们的甜甜圈和第二次帮助,我们只需这样做:

myDonut.save();
mySecondHelping.save();
Run Code Online (Sandbox Code Playgroud)

骨干很聪明.如果您刚刚创建了一个甜甜圈资源,它将没有来自服务器的ID.它有一个叫做cID的东西,这是Backbone在内部使用的,但由于它没有官方ID,它知道它应该创建一个新的资源并发送一个POST请求.如果从服务器获得模型,如果一切正确,它可能会有一个ID.在这种情况下,当你保存()Backbone假设你想要更新服务器,它将发送一个PUT.要获取特定资源,您需要使用Backbone方法.fetch()并发送GET请求.当您在模型上调用.destroy()时,它将发送DELETE.

在前面的例子中,我从未明确告诉Backbone URI在哪里.让我们在下一个例子中这样做.

thirdHelping = Backbone.Model.extend({
    url: 'donut'
});
thirdHelping.set({id:15});  // Set the id attribute of model to 15
thirdHelping.fetch();  // Backbone assumes this model exists on server as ID 15
Run Code Online (Sandbox Code Playgroud)

Backbone将获得第三个帮助http://localhost:8888/donut/15它将简单地添加/ donut stem到您的站点根目录.

如果你还在我身边,那很好.我认为.除非你感到困惑.但无论如何我们都会跋涉.第二部分是SERVER端.我们已经讨论了不同的HTTP动词以及这些动词背后的语义含义.您,Backbone和您的服务器必须共享的含义.

您的服务器需要了解GET,POST,PUT和DELETE请求之间的区别.正如您在上面的示例中看到的那样,GET,PUT和DELETE都可以指向相同的URI.http://localhost:8888/donut/07除非您的服务器可以区分这些HTTP请求,否则将对如何处理该资源非常困惑.

这是您开始考虑RESTful服务器端代码的时候.有些人喜欢Ruby,有些人喜欢.net,我喜欢PHP.特别是我喜欢SLIM PHP微框架.SLIM PHP是一个微框架,它具有非常优雅和简单的工具集来处理RESTful活动.您可以像上面的示例中那样定义路由(URI),并且根据调用是GET,POST,PUT还是DELETE,它将执行正确的代码.还有其他类似于SLIM的解决方案,如Recess,Tonic.我相信像Cake和CodeIgniter这样的大型框架也会做类似的事情,尽管我喜欢minimal.我说我喜欢Slim吗?;-)

这是服务器上的摘录代码可能看起来(即具体关于路由.)

$app->get('/donut/:id', function($id) use ($app) {
    // get donut model with id of $id from database.
    $donut = ...

    // Looks something like this maybe:
    // $donut = array('id'=>7, 'flavor'=>'chocolate', 'price'=>'1.00')

    $response = $app->response();
    $response['Content-Type'] = 'application/json';
    $response->body(json_encode($donut));
});
Run Code Online (Sandbox Code Playgroud)

这里需要注意的是Backbone需要一个JSON对象.如果可以,请始终让您的服务器将内容类型指定为'application/json'并以json格式对其进行编码.然后,当Backbone收到JSON对象时,它知道如何填充请求它的模型.

使用SLIM PHP,路由的运行方式与上述类似.

$app->post('/donut', function() use ($app) {
    // Code to create new donut
    // Returns a full donut resource with ID
});
$app->put('/donut/:id', function($id) use ($app) {
    // Code to update donut with id, $id
    $response = $app->response();
    $response->status(200);  // OK!
    // But you can send back other status like 400 which can trigger an error callback.
});
$app->delete('/donut/:id', function($id) use ($app) {
    // Code to delete donut with id, $id
    // Bye bye resource
});
Run Code Online (Sandbox Code Playgroud)

所以你几乎完成了全程往返!去喝汽水.我喜欢Diet Mountain Dew.给我一个.

一旦您的服务器处理请求,对数据库和资源执行某些操作,准备响应(无论是简单的http状态编号还是完整的JSON资源),然后数据将返回到Backbone进行最终处理.

使用save(),fetch()等方法 - 您可以在成功和错误时添加可选的回调.以下是我如何设置这个特殊蛋糕的示例:

Cake = Backbone.Model.extend({
    defaults: {
        type: 'plain',
        nuts: false
    },
    url: 'cake'
});

myCake = new Cake();
myCake.toJSON()  // Shows us that it is a plain cake without nuts

myCake.save({type:'coconut', nuts:true}, {
    wait:true,
    success:function(model, response) {
        console.log('Successfully saved!');
    },
    error: function(model, error) {
        console.log(model.toJSON());
        console.log('error.responseText');
    }
});

// ASSUME my server is set up to respond with a status(403)
// ASSUME my server responds with string payload saying 'we don't like nuts'
Run Code Online (Sandbox Code Playgroud)

这个例子有几个不同的东西.您将看到我的蛋糕,而不是在保存之前设置()属性,我只是将新属性传递给我的保存调用.Backbone非常擅长在整个地方获取JSON数据并像冠军一样处理它.所以我想用椰子和坚果保存我的蛋糕.(这是2个坚果吗?)无论如何,我把两个物品传给了我.属性JSON对象和一些选项.第一个,{wait:true}表示在服务器端跳闸成功之前不更新我的客户端模型.当服务器成功返回响应时,将发生成功回调.但是,由于此示例导致错误(200以外的状态将指示Backbone使用错误回调),我们将获得没有更改的模型的表示.它应该仍然是平原而且没有坚果.我们还可以访问服务器发回的错误对象.我们发回了一个字符串,但它可能是具有更多属性的JSON错误对象.它位于error.responseText属性中.是的,'我们不喜欢坚果.'

恭喜.您已经完成了第一次完整的往返旅程,从设置模型,保存服务器端,然后返回.我希望这个回答史诗能让你了解这一切是如何结合在一起的.当然,我正在游历的很多细节,但Backbone的基本思想,RESTful动词,服务器端动作,响应都在这里.继续浏览Backbone文档(与其他文档相比,这是非常容易阅读的),但请记住,这需要时间来包装.你保持的越多,你就会越流利.我每天都会通过Backbone学到一些新知识,当你开始跳跃并看到你在这个框架中的流畅度增长时,它会变得非常有趣.:-)

快乐的编码!

编辑:可能有用的资源:

关于SO的其他类似答案: 如何使用Backbone生成模型ID

关于REST:http : //rest.elkstein.org/ http://www.infoq.com/articles/rest-introduction http://www.recessframework.org/page/towards-restful-php-5-basic-提示

  • 我最终对此有所了解.我记得当我第一次开始使用Backbone并且遇到像提问者这样的问题时,我写了一些回复有点太有趣了.我确信在我的匆忙中我犯了一些错误或错过了一些重要的批评"啊哈!" 如果我这样做,请告诉我.:-P (9认同)
  • 心灵的回答至少可以说......我正在努力把握你提到的所有事情......尽管你是对的,但是REST事情看起来有点困难,你不能在这个问题中解释我的REST ......我我会再次检查并接受它... ...再次详细解答... (6认同)
  • @testndtv我最终回答你的问题了吗?√标志将不胜感激. (5认同)
  • 当我有空的时候,我会用一系列可以帮助你完成任务的好参考资料来更新我的答案.我不能给你一把木剑来面对危险的世界,但我可以给你一些帮助我的网站的资源链接.:-) (2认同)
  • 毫无疑问,你确实以超出预期的方式回答了这个问题......我现在已经接受了答案......再次感谢你的帮助.. (2认同)
  • 史诗般的回答是史诗般的.@orangewarp,你有博客吗?我很想读更多你的作品! (2认同)