21

我正在设置主干同步机制,有点困惑在哪里为模型生成 id。

当我创建一个新模型时,主干是否应该生成和设置 id,或者我应该实现一个 id 生成方法,或者是否有某种机制可以将数据“PUT”到服务器,生成 id 和返回带有 id 的模型?

4

3 回答 3

56

我提供第二个答案来简化您需要研究的代码,以获得您正在思考的要点 - 从模型到服务器的实际回合以及 id 如何发挥它们的作用。

假设您定义了一个模型 - 让我们使用侏罗纪公园。

// Define your model
var Dinosaur = Backbone.Model.extend({
    defaults: {
        cavemanEater: undefined    // Has one property, nom nom or not.
    },
    urlRoot: 'dino'               // This urlRoot is where model can be saved or retrieved
});

var tRex = new Dinosaur({'cavemanEater':true});

您现在已经实例化了一个肉食者恐龙。怒吼。

console.log(tRex);

您应该注意的是,在 tRex 的属性中,您的模型没有 id。相反,您将看到一个 cID,您可以将其视为 Backbone 自动分配给您的模型的临时 id。当模型没有 id 时,它被认为是新的。持久化模型(数据库或本地存储)的概念允许您在创建该资源后返回该资源并执行保存(PUT)或销毁(DELETE)等操作。如果您无法再次直接指向该资源,将很难找到该资源!为了找到该资源,您的模型需要一个 ID,它目前没有。

因此,正如上述答案所解释的,为 Backbone 提供资源 ID 是您的数据库(或本地存储或其他解决方案)的工作。大多数情况下,这来自资源 ID 本身,也就是您的模型在某个表中的主键 ID。

通过我的设置,我使用 PHP 和 mySQL。我会有一个名为 Dinosaur 的表,每一行都是我的恐龙模型的持久表示。所以我有一个 id 列(唯一的自动递增 int)和cavemanEater(bool)。

数据通信流程是这样发生的。

  1. 您创建一个模型。
  2. 该模型是新的,因此它只有一个 cID - 没有正确的 ID。
  3. 您保存模型。
  4. 您的模型的 json 表示已发送到您的服务器(POST)
  5. 您的服务器将其保存到表中并为其提供资源 ID。
  6. 您的服务器发送回数据 {id:uniqueID} 的 json 表示
  7. Backbone 接收到这个带有 id 的 json 表示
  8. Backbone 使用 id 自动更新您的模型。

这是带注释的代码的样子。

客户:

tRex.save();
// {'cavemanEater':true} is sent to my server
// It uses the urlRoot 'dino' as the URL to send. e.g. http://www.example.com/dino

服务器:

// Is setup to accept POST requests on this specific ROUTE '/dino'
// Server parses the json into something it can work with, e.g. an associative array
// Server saves the data to the database. Our data has a new primary id of 1.
// Data is now persisted, and we use this state to get the new id of this dino.

$dinoArray = array('id'=>1, 'cavemanEater'=>true);
$dinoJSON = json_encode($dinoArray);

// Server does something to send $dinoJSON back.

客户:

// If successful, receives this json with id and updates your model.

现在你的 tRex 有一个 id = 1。或者我应该说......

tRex.toJSON();
// RETURNS {'id':'1', 'cavemanEater':'true'}

恭喜。如果你这样做tRex.isNew(),它将返回 false。

骨干很聪明。它知道 POST 已经具有资源 ID 的新模型和 PUT 模型。

下次您这样做时:

tRex.save();

Backbone 将向以下 URL 发出 PUT 请求。

http://www.example.com/dino/1

顺便说一句,这是默认行为。但是您会注意到 URL 与保存不同。在服务器上,您需要一个接受 /dino/:id 而不是 /dino 的路由

默认情况下,它将为您的模型使用 /urlRoot/:id 路由模式,除非您另行调整。

不幸的是,恐龙已经灭绝了。

tRex.destroy();

这将调用......你能猜到吗?是的。对 /dino/1 的删除请求。

您的服务器必须区分对不同路由的不同请求,以便 Backbone 工作。有几种服务器端技术可以做到这一点。

如果你使用 Ruby,有人提到了 Sinatra。就像我说的,我使用 PHP,我使用 SLIM PHP Framework。它的灵感来自 Sinatra,所以很相似,我喜欢它。作者写了一些干净的代码。不过,这些 RESTful 服务器实现的工作原理不在本次讨论的范围之内。

我认为这是没有 id 的新 Backbone 数据的基本完整旅行,通过 Internet 到它生成的服务器,然后发回资源 id,让你的模型从此过上幸福的生活。(或者destroy()不是……)

我不知道这对你来说是否太初学者,但希望它能帮助遇到这个问题的其他人。Backbone 编程真的很有趣。

其他类似的答案: 如何保存 Backbone JS 模型数据

于 2012-05-29T05:46:56.967 回答
9

或者是否有某种机制我将数据“PUT”到服务器,它生成 id 并返回带有 id 的模型?

有点儿。当您调用模型的保存方法时,主干会生成一个 POST XHR,并且您的应用程序服务器应该以包含 id 的 JSON 响应。你可以在这里看到一个例子:http: //addyosmani.com/blog/building-backbone-js-apps-with-ruby-sinatra-mongodb-and-haml/

引用链接:

post '/api/:thing' do 
  # parse the post body of the content being posted, convert to a string, insert into 
  # the collection #thing and return the ObjectId as a string for reference 
  oid = DB.collection(params[:thing]).insert(JSON.parse(request.body.read.tos)) 
  "{\"id\": \"#{oid.to_s}\"}" 
end

如果您不了解 Ruby,请记住该方法自动返回的最后一个表达式是什么。

于 2012-05-29T01:27:47.067 回答
4

我从您的问题中了解到的是,您希望拥有一个包含服务器上存在的模型的集合。为了将这些模型放入集合中,您必须在集合中添加调用“fetch()”。

url 将是“/users”或类似的东西,它必须返回一个包含用户数据的对象数组。然后将数组中的每个项目传递给 UserCollection.add()。好吧,实际上它会一次全部通过,但你明白了。

在此之后,您的集合被填充。模型上的 url 用于更新和保存单个模型。集合的 url 也将用于创建模型。Backbone 的同步是 RESTful 的,就像 Ruby on Rails 一样。实际上,您可以在 Ruby on Rails 的文档中了解更多信息:

http://guides.rubyonrails.org/routing.html

您通常会为您的模型设置与控制器不同的 url。填充您的集合后,您有每个模型的 ID,因为它们来自服务器。

现在,当您根据用户输入添加新模型时,您将执行以下操作:

var HomeModel = Backbone.Model.extend({
    defaults: {
        lead: "not logged in",
    },

    url: 'test.php',

    initialize: function(){
        _.bindAll(this, 'handleSave', 'handleError');
        // Save already knows if this.isNew.
        this.save(undefined, {success: this.handleSave, error: this.handleError});
    },

    handleSave: function(model, response){
        this.model.reset(model);
    },

    handleError: function(){

    },
});

var HomeView = Backbone.View.extend({
    initialize: function() {
        _.bindAll(this, 'render');
        this.model = new HomeModel();
        this.model.bind("change", this.render);
    },

    el: 'div',

    render: function() {    
        // Do things to render...
    }
});

var homeView = new HomeView();

这个例子来自我回答的别人的问题,我只是添加了相关的东西。

一般的想法是在创建模型时保存模型,如果您在其他地方需要它,您可以将代码移动到模型的函数中并根据事件或其他任何内容调用它。

于 2012-05-29T00:04:41.263 回答