关于其余部分:使用HATEOAS和Backbone.js

 2021-04-09 

Using HATEOAS and Backbone.js

我已经开始尝试使用Backbone.js,并且对Backbone.Model上url属性的文档的文档感到震惊。

尤其是,我正在构建一个使用HATEOAS /超媒体来驱动客户端的REST API。

我可以看到Backbone的默认行为(为集合中的项目建立URL本身)的有用性,但就我而言,我更希望模型URL由解析的数据构建。

有人在Backbone上进行扩展/构建来做到这一点吗?也许以HAL之类的"标准"为基础吗?

编辑:

为澄清起见,假设我有以下内容:

获取/订单>>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
  {
    "_links": {
      "self":"/orders/123"
     }
    "name":"Order #123",
    "date":"2012/02/23"
  },
  {
    "_links": {
      "self":"/orders/6666"
     }
    "name":"Order #666",
    "date":"2012/03/01"
  },
]

,我有一个订购模型,例如:

1
2
var Order = Backbone.Model.extend({
});

我希望将url属性自动从HAL中的" self "引用中拉出。我认为创建一个新的基本模型类似(未测试):

1
2
3
4
5
var HalModel = Backbone.Model.extend({
  url: function() {
    return get("_links").self;
  },
});

有何想法?


我已经扩展了Backbone 来做到这一点,该库可以在这里找到:

https://github.com/mikekelly/backbone.hal


感谢@Pete的澄清。

我想我明白你的建议,我想它可以奏效。但是,在您的示例中,必须首先知道/Orders网址,然后才能获得订单。而且,如果您将json修改为具有id属性,则将非常接近主干的默认实现。

现在,如果您只想使用通用模型或基本模型(例如HALModel)并仅将其与数据一起引导,则您的方法可能会有用并且肯定可以工作。但是,我将看一下覆盖解析以拉出URL并将其设置在模型上:

1
2
3
4
5
parse: function(response) {
    this.url = response._links.self;
    delete response._links;
    return response;
}


我在这里补充Simon的回答,以说明如何使用gomoob / backbone.hateoas轻松完成此操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Instanciation of an Hal.Model object is done the same way as you're
// used to with a standard Backbone model
var user = new Hal.Model({
    firstName:"John",
    lastName:"Doe",
    _links: {
        avatar: {
            href:"http://localhost/api/users/1/avatar.png"
        },
        self: {
            href:"http://localhost/api/users/1"
        }
    },
    _embedded: {
        address: {
           "city" :"Paris",
           "country" :"France",
           "street" :"142 Rue de Rivoli",
           "zip" :"75001",
           "_links" : {
               "self" : {
                   "href" :"http://localhost/api/addresses/1"
                }
            }
        }
    }
});

// Now we you can easily get links, those lines are equivalent
var link1 = user.getLink('avatar');
var link2 = user.getLinks().get('avatar');

// So getting self link is simple too
var self = user.getLink('self');

// All the Hal.Link objects returned by backbone.hateoas are in fact
// standard Backbone models so its standard Backbone
link1.get('href');
link1.getHref();

// You can do more with shortcut methods if your HAL links
// have more properties
link1.get('deprecation');
link1.getDeprecation();
link1.get('name');
link1.getName();
link1.get('hreflang');
link1.getHreflang();
link1.get('profile');
link1.getProfile();
link1.get('title');
link1.getTitle();
link1.get('type');
link1.getType();
linke1.get('templated');
link1.isTemplated();

// You can also manipulate embedded resources if you need
user.getEmbedded('address').get('city');
user.getEmbedded('address').getLink('self');
...

最后,我们提供了Hal.Model.url()实现,该实现比标准Backbone url()更强大,如果您使用HAL,则非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// By default url() returns the href of the self link if this self
// link is present
user.url();

// If the self link is not defined then url() has the same behavior
// as standard Backbone url() method
// My user is link to a user collection having a URL equal to
// 'http://localhost/user1'
user.url(); // http://localhost/users/1

// My user is not link to a user collection in this case the URL is
// generate using the model urlRoot property by default
user.urlRoot = 'http://myserver/users';
user.url(); // http://localhost/users/1

// backbone.hateoas also allows you to define an application wide root
// URL which prevent to use absolute URLs everywhere in your code
Hal.urlRoot = 'http://localhost/api';  // HAL root API URL

var user = new Hal.Model({ id : 1});
user.urlMiddle = 'users';
user.url(); // http://localhost/api/users/1

希望这会有所帮助,如果您需要帮助,请不要犹豫在我们的github上发布问题。


您可以覆盖模型上的url函数,以根据需要计算URL;它是完全可扩展的。