【发布时间】:2016-11-15 23:34:58
【问题描述】:
在多个视图之间共享一个 Backbone 模型是一种相当常见的情况。尽管如此,假设这个模型是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 方法后获取自己,但用户可以到达页面或重新加载已经登录的浏览器。此外,用户可以登陆任何页面,没有办法说他会在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's model.changed 文档参考和下划线的_.isEmpty's。
哪种方式更干净?还有其他我可能错过的方法吗?
【问题讨论】:
标签: javascript backbone.js model synchronization