一个用于多个视图的主干模型,谁处理 fetch()
One Backbone model for several views, who handles the fetch()?
在多个视图之间共享主干模型是一种相当普遍的情况。尽管如此,假设这个模型是一个UserModel
。它处理多种方法,例如允许用户注册或登录。
记录用户时,将调用 fetch 以获取用户的数据。因此,模型无法在其initialize
方法中使用this.fetch()
获取自身。
从哪里取来?如何?
这是我们的简单UserModel
:
const UserModel = Backbone.Model.extend({
// get url for 'me' (ie connected user)
url() {
return app.endpoint + '/users/me/' + app.conToken;
},
login(email, password, rememberMe, callback) {
…
},
signup(email, password, firstname, lastname, callback) {
…
}
});
现在假设它由两者共享:
HomeView
& CartView
app.HomeView = Backbone.View.extend({
template: app.tpl.home,
initialize() {
// model is passed @ instanciation
this.model.fetch();
this.listenTo(this.model, 'sync', this.render);
},
render() {
…
}
});
app.CartView = Backbone.View.extend({
template: app.tpl.cart,
initialize() {
// model is passed @ instanciation
this.model.fetch();
this.listenTo(this.model, 'sync', this.render);
},
render() {
…
}
});
现在,如果我实例化HomeView
,userModel
将被获取。但是,如果在以后的某个时候,我CartView
实例化,将再次获取相同的模型。这会产生一个无用的http请求。
基本上,模型可以在成功调用其login
方法后获取 istself,但用户可以到达页面或重新加载已经登录的浏览器。此外,用户可以登陆任何页面,没有办法说他会在CartView
之前HomeView
。
我看到有两种选择。UserModel
都可以巧妙地处理多个fetch
调用,如下所示:
const UserModel = Backbone.Model.extend({
// get url for 'me' (ie connected user)
url() {
return app.endpoint + '/users/me/' + app.conToken;
},
isSync() {
// an hour ago
let hourAgo = Date.now() - 3600000;
// data has been fetched less than an hour ago
if (this.fetchTime && hourAgo > this.fetchTime) return true;
return false;
},
fetch() {
// has not already fetched data or data is older than an hour
if (!this.isSync()) {
this.fetchTime = Date.now();
this.fetch();
return;
}
// trigger sync without issuing any http call
this.trigger('sync');
},
…
});
这样,我就可以根据需要多次调用this.model.fetch()
,在视图中是无状态的。
或者,我可以在视图层上处理它:
app.HomeView = Backbone.View.extend({
template: app.tpl.home,
initialize() {
// model is passed @ instanciation
// fetch model if empty
if (_.isEmpty(this.model.changed)) this.fetch();
// render directly if already populated
else this.render();
// render on model sync
this.listenTo(this.model, 'sync', this.render);
},
render() {
…
}
});
如果需要,Backbone的model.changed
文档参考和Underscore的_.isEmpty
。
哪种方式更干净?还有其他我可能错过的方法吗?
个人偏好不是覆盖fetch
而是实现包装器函数,如customFetch
const UserModel = Backbone.Model.extend({
// get url for 'me' (ie connected user)
url() {
return app.endpoint + '/users/me/' + app.conToken;
},
isSync() {
// an hour ago
let hourAgo = Date.now() - 3600000;
// data has been fetched less than an hour ago
if (this.fetchTime && hourAgo > this.fetchTime) return true;
return false;
},
customFetch() {
// has not already fetched data or data is older than an hour
if (!this.isSync()) {
this.fetchTime = Date.now();
this.fetch();
return;
}
// trigger sync without issuing any http call
this.trigger('sync');
},
…
});
您提供的代码示例最终会进入循环(this.fetch
调用自身...(,所以我个人的偏好是将核心主干功能包装在另一个函数中。
我什至会拥有自己的自定义Model
,该由我使用的所有模型扩展。例如:
const MyModel = Backbone.Model.extend({
isSync() {
// an hour ago
let hourAgo = Date.now() - 3600000;
// data has been fetched less than an hour ago
return (this.fetchTime && hourAgo > this.fetchTime);
},
customFetch() {
this.fetch();
},
});
然后UserModel
将覆盖customFetch
,如下所示:
const UserModel = MyModel.extend({
customFetch() {
// has not already fetched data or data is older than an hour
if (!this.isSync()) {
this.fetchTime = Date.now();
this.fetch();
return;
}
// trigger sync without issuing any http call
this.trigger('sync');
},
});
可能不是最好的方法。就我个人而言,这将是阅读然后稍后扩展的简单方法。我想这个customFetch
将用于某些/所有模型,以便可以适当修改。
- 在MVVM视图模型中处理应用程序范围的元素
- sailsjs在创建两个模型时的错误处理
- 如果模型开始为空,如何处理ngRepeat模型中的新项
- HTML5导航处理模型--
- 如何在ember.js中将多个模型处理成一个模板/路由
- 如何等到find方法完成后再在Ember模型中进行进一步处理
- Jquery OOP 模型阻止默认然后调用基处理程序
- 我们如何处理包含带有秘银的子数组的数据模型
- 使用Spine.Model.Ajax,如何在模型更新时处理响应的JSON中的额外属性
- 如何通过关系处理特定于父级的模型值
- Durandal:在找不到视图/视图模型时处理 RequireJS 错误
- AngularJS:这是编写处理模型/内容更新的指令的正确方法吗?
- 当 ng 模型输入为数字时,处理它
- 如果在 jQuery 委托事件处理程序中更改了 AngularJS 模型,它不会立即更新
- 在 Backbone Js 中处理模型事件
- 如何处理嵌套在关系模型中的集合
- 如何处理主干视图中的异步链接模型
- 如何在挖空视图模型中处理空对象和满对象
- Angularjs处理承诺和模型
- 在Sails.js中传递用于模型处理的文件流