基于另一个 Backbone 个模型初始化 Backbone 个模型
Initialize Backbone Models based on another Backbone Model
我有一个 config.json
将作为 Backbone 模型加载到我的应用程序中,例如:
var Config = Backbone.Model.extend({
defaults: {
base: ''
},
url: 'config.json'
});
其他模型应该依赖于 Config
中包含的一些数据,例如:
var ModelA = Backbone.Collection.extend({
initialize: function(){
//this.url should be set to Config.base + '/someEndpoint';
}
});
在上面的示例中,ModelA
的 url
属性 取决于 Config
的 base
属性 的值。
如何在 Backbone 应用程序中正确设置它?
据我所知,您的基本问题是:
- 我们将如何获得配置模型的实例?
- 我们将如何使用配置模型来设置依赖模型的
url
?
- 我们如何确保我们不会过早地在依赖模型上使用
url
函数?
有很多方法可以解决这个问题,但我会提出一些具体建议,这样我就可以提供指导和代码,"get it done," 可以这么说。
我认为处理第一个问题的最佳方法是使该配置模型成为单例。我将在下面的 backbone-singleton GitHub 页面提供代码,但我不希望答案在垂直方向上很长,直到我完成解释,所以请继续阅读...
var MakeBackboneSingleton = function (BackboneClass, options) { ... }
接下来,我们利用 jQuery
创建一个单例 AppConfiguration
和一个 deferred
属性。 fetch
的结果会提供always(callback)
、done(callback)
等
var AppConfiguration = MakeBackboneSingleton(Backbone.Model.extend({
defaults: {
base: null
},
initialize: function() {
this.deferred = this.fetch();
},
url: function() {
return 'config.json'
}
}));
现在,是时候定义依赖模型了 DependentModel
,它看起来像您的模型。它将调用 AppConfiguration()
来获取实例。
请注意,由于 MakeBackboneSingleton
,以下是全部 true
:
var instance1 = AppConfiguration();
var instance2 = new AppConfiguration();
instance1 === instance2; // true
instance1 === AppConfiguration() // true
模型将在提供 id
时自动 fetch
,但仅在 我们完成 AppConfiguration
的提取后 。请注意,您可以使用 always
、then
、done
等
var DependentModel = Backbone.Model.extend({
initialize: function() {
AppConfiguration().deferred.then(function() {
if (this.id)
this.fetch();
});
},
url: function() {
return AppConfiguration().get('base') + '/someEndpoint';
}
});
现在终于,把它们放在一起,你可以实例化一些模型了。
var newModel = new DependentModel(); // no id => no fetch
var existingModel = new DependentModel({id: 15}); // id => fetch AFTER we have an AppConfiguration
只要 AppConfiguration
的提取成功,第二个就会自动提取。
这里有 MakeBackboneSingleton
给你(同样来自 GitHub 存储库):
var MakeBackboneSingleton = function (BackboneClass, options) {
options || (options = {});
// Helper to check for arguments. Throws an error if passed in.
var checkArguments = function (args) {
if (args.length) {
throw new Error('cannot pass arguments into an already instantiated singleton');
}
};
// Wrapper around the class. Allows us to call new without generating an error.
var WrappedClass = function() {
if (!BackboneClass.instance) {
// Proxy class that allows us to pass through all arguments on singleton instantiation.
var F = function (args) {
return BackboneClass.apply(this, args);
};
// Extend the given Backbone class with a function that sets the instance for future use.
BackboneClass = BackboneClass.extend({
__setInstance: function () {
BackboneClass.instance = this;
}
});
// Connect the proxy class to its counterpart class.
F.prototype = BackboneClass.prototype;
// Instantiate the proxy, passing through any arguments, then store the instance.
(new F(arguments.length ? arguments : options.arguments)).__setInstance();
}
else {
// Make sure we're not trying to instantiate it with arguments again.
checkArguments(arguments);
}
return BackboneClass.instance;
};
// Immediately instantiate the class.
if (options.instantiate) {
var instance = WrappedClass.apply(WrappedClass, options.arguments);
// Return the instantiated class wrapped in a function so we can call it with new without generating an error.
return function () {
checkArguments(arguments);
return instance;
};
}
else {
return WrappedClass;
}
};
我有一个 config.json
将作为 Backbone 模型加载到我的应用程序中,例如:
var Config = Backbone.Model.extend({
defaults: {
base: ''
},
url: 'config.json'
});
其他模型应该依赖于 Config
中包含的一些数据,例如:
var ModelA = Backbone.Collection.extend({
initialize: function(){
//this.url should be set to Config.base + '/someEndpoint';
}
});
在上面的示例中,ModelA
的 url
属性 取决于 Config
的 base
属性 的值。
如何在 Backbone 应用程序中正确设置它?
据我所知,您的基本问题是:
- 我们将如何获得配置模型的实例?
- 我们将如何使用配置模型来设置依赖模型的
url
? - 我们如何确保我们不会过早地在依赖模型上使用
url
函数?
有很多方法可以解决这个问题,但我会提出一些具体建议,这样我就可以提供指导和代码,"get it done," 可以这么说。
我认为处理第一个问题的最佳方法是使该配置模型成为单例。我将在下面的 backbone-singleton GitHub 页面提供代码,但我不希望答案在垂直方向上很长,直到我完成解释,所以请继续阅读...
var MakeBackboneSingleton = function (BackboneClass, options) { ... }
接下来,我们利用 jQuery
创建一个单例 AppConfiguration
和一个 deferred
属性。 fetch
的结果会提供always(callback)
、done(callback)
等
var AppConfiguration = MakeBackboneSingleton(Backbone.Model.extend({
defaults: {
base: null
},
initialize: function() {
this.deferred = this.fetch();
},
url: function() {
return 'config.json'
}
}));
现在,是时候定义依赖模型了 DependentModel
,它看起来像您的模型。它将调用 AppConfiguration()
来获取实例。
请注意,由于 MakeBackboneSingleton
,以下是全部 true
:
var instance1 = AppConfiguration();
var instance2 = new AppConfiguration();
instance1 === instance2; // true
instance1 === AppConfiguration() // true
模型将在提供 id
时自动 fetch
,但仅在 我们完成 AppConfiguration
的提取后 。请注意,您可以使用 always
、then
、done
等
var DependentModel = Backbone.Model.extend({
initialize: function() {
AppConfiguration().deferred.then(function() {
if (this.id)
this.fetch();
});
},
url: function() {
return AppConfiguration().get('base') + '/someEndpoint';
}
});
现在终于,把它们放在一起,你可以实例化一些模型了。
var newModel = new DependentModel(); // no id => no fetch
var existingModel = new DependentModel({id: 15}); // id => fetch AFTER we have an AppConfiguration
只要 AppConfiguration
的提取成功,第二个就会自动提取。
这里有 MakeBackboneSingleton
给你(同样来自 GitHub 存储库):
var MakeBackboneSingleton = function (BackboneClass, options) {
options || (options = {});
// Helper to check for arguments. Throws an error if passed in.
var checkArguments = function (args) {
if (args.length) {
throw new Error('cannot pass arguments into an already instantiated singleton');
}
};
// Wrapper around the class. Allows us to call new without generating an error.
var WrappedClass = function() {
if (!BackboneClass.instance) {
// Proxy class that allows us to pass through all arguments on singleton instantiation.
var F = function (args) {
return BackboneClass.apply(this, args);
};
// Extend the given Backbone class with a function that sets the instance for future use.
BackboneClass = BackboneClass.extend({
__setInstance: function () {
BackboneClass.instance = this;
}
});
// Connect the proxy class to its counterpart class.
F.prototype = BackboneClass.prototype;
// Instantiate the proxy, passing through any arguments, then store the instance.
(new F(arguments.length ? arguments : options.arguments)).__setInstance();
}
else {
// Make sure we're not trying to instantiate it with arguments again.
checkArguments(arguments);
}
return BackboneClass.instance;
};
// Immediately instantiate the class.
if (options.instantiate) {
var instance = WrappedClass.apply(WrappedClass, options.arguments);
// Return the instantiated class wrapped in a function so we can call it with new without generating an error.
return function () {
checkArguments(arguments);
return instance;
};
}
else {
return WrappedClass;
}
};