【发布时间】:2012-04-28 16:51:30
【问题描述】:
在backbone.js 中,您必须手动设置每个模型的rooturl。有没有办法我们可以在一个位置设置一次,然后所有模型都会使用它?
例如。 api.site.com 将是 REST 服务,但出于测试目的,它可能位于 localhost:1000 我需要能够轻松更改服务的根 url,而不是在存在的许多模型中到处都是应用程序。
【问题讨论】:
标签: backbone.js
在backbone.js 中,您必须手动设置每个模型的rooturl。有没有办法我们可以在一个位置设置一次,然后所有模型都会使用它?
例如。 api.site.com 将是 REST 服务,但出于测试目的,它可能位于 localhost:1000 我需要能够轻松更改服务的根 url,而不是在存在的许多模型中到处都是应用程序。
【问题讨论】:
标签: backbone.js
在将 Backbone 与 AMD (require.js) 结合使用时,我一直在尝试最优雅的方式来执行此操作。这是我想出的,也是[迄今为止]最好的。
首先,按照here 所述,引导数据。
index.htm(应用程序入口点)
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script>
var require = {
config: {
// key name is module, value is data to give module
'models/Base': {
apiUrl: '/some/path/to/api',
}
}
}
</script>
<script data-main="js/main" src="vendor/require/require-jquery.js"></script>
</head>
<body></body>
</html>
接下来,为 Backbone 模型定义一个基类,如下所示:
js/models/Base.js(请注意此模块名称与上面配置中的模块名称匹配)
define(['module', 'backbone'],
function(module, Backbone){
return Backbone.Model.extend({
getApiUrl: function(){
return module.config().apiUrl;
}
});
}
);
最后,从该基础扩展所有 Backbone 模型,如下所示:
js/models/User.js
define(['models/Base'],
function(BaseModel){
return BaseModel.extend({
urlRoot: function(){
return this.getApiUrl() + '/user';
}
// ... more cool stuff here
});
}
);
这与关于 Backbone 和 Require.JS 的 earlier question I had 切线相关。
【讨论】:
我的理解是:
你有几个模型:model1 和 model2
根 URL 可以是 http://api.site.com 或 http://localhost:8080,具体取决于您是在本地工作还是在外部工作。有一天它可能是http://api.anothersite.com
那么我会做这样的事情:
// Global var before any other JS code, you comment line depending on which one applies
var ROOT = 'http://api.site.com'
// var ROOT = 'http://localhost:8080'
var Model1 = Backbone.Model.extend({
urlRoot: ROOT+'/model1',
...
});
var Model2 = Backbone.Model.extend({
urlRoot: ROOT+'/model2',
...
});
但请注意这一点,您可能会在提交时忘记从一个 url 切换到另一个。如果它们适用,最好处理相对路径。
【讨论】:
在我看来,实现这一点的最佳方法是覆盖 Backbone.sync 方法,并在其中添加您的根 url。这是因为模型不负责了解 API 域。
// Cache Backbone.sync for later use
var sync = Backbone.sync;
Backbone.sync = function(method, model, options){
options.beforeSend = function(){
this.url = API_ROOT_URL + this.url;
};
return sync.call(this, method, model, options);
};
然后您可以像往常一样创建模型:
var Resource = Backbone.Model.extend({
urlRoot: '/resources',
});
我使用相同的方法将.json 扩展附加到所有 URL 以防止 JSON 通过浏览器缓存闪烁。
【讨论】:
beforeSend() 在请求已经被原始 url 打开后调用。
beforeSend的用法; beforeSend 类型:Function( jqXHR jqXHR, PlainObject settings ) 一个预请求回调函数,可用于在发送之前修改 jqXHR(在 jQuery 1.4.x 中为 XMLHTTPRequest)对象。使用它来设置自定义标题等。 jqXHR 和设置对象作为参数传递。这是一个 Ajax 事件。在 beforeSend 函数中返回 false 将取消请求。从 jQuery 1.5 开始,无论请求类型如何,都将调用 beforeSend 选项。
改编自https://coderwall.com/p/8ldaqw/add-a-root-url-to-all-backbone-api-request
var backboneSync = Backbone.sync;
Backbone.sync = function (method, model, options) {
/*
* Change the `url` property of options to begin
* with the URL from settings
* This works because the options object gets sent as
* the jQuery ajax options, which includes the `url` property
*/
options = _.extend(options, {
url: API_ROOT + _.result(model, 'url')
});
/*
* Call the stored original Backbone.sync
* method with the new url property
*/
backboneSync(method, model, options);
};
【讨论】:
不确定手动为每个模型设置 urlRoot 的确切含义。
大概你会这样做
var MyModel = Backbone.Model.extend({
urlRoot: '/mymodel',
...
});
对吗?然后每个模型实例自然有相同的urlRoot。任何其他模型实例比如MyOtherModel 都会有一些不同的urlRoot。
如果由于某种原因您需要使用相同的urlRoot,我猜这是因为模型共享属性。这应该暗示继承或扩展,以便您可以这样做:
var BaseModel = Backbone.Model.extend({
urlRoot: '/mymodel'
});
var MyModel = BaseModel.extend({
...
});
【讨论】:
只需从 '/' 开始您的网址。 因此,您将不依赖于本地主机或真实域。
【讨论】:
这是一个很老的帖子,但我认为我的版本可能对某人有用。我将骨干网与 require.js 一起使用,并且我的服务器端和客户端完全分开。当我声明 requirejs 脚本时,我会同时告知客户端应用程序的 API 根在哪里:
<script
data-main="js/main"
data-api-url="https://api/v1/"
src="js/require.js">
</script>
然后我进入我的主干模块:
var $scriptEl = $('script[data-main]'),
base = $scriptEl.attr('data-api-url');
var BaseModel = Backbone.Model.extend({
urlRoot: base
});
var model = BaseModel.extend({});
这是我能找到的最优雅的方式..
【讨论】: