在多个视图之间共享Backbone模型是一种相当常见的情况。不过,我们假设这个模型是UserModel
。它处理多种方法,允许用户注册或登录。
当用户被记录时,调用fetch来获取用户的数据。因此,模型无法在this.fetch()
方法中使用initialize
获取自身。
从哪里拿出来的?怎么样?
这是我们的简单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
方法后获取,但用户可以到达页面或重新加载已登录的浏览器。此外,用户可以登陆任何页面,那里和#39;无法说他在HomeView
之前前往CartView
。
我看到有两种选择。 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
doc reference&下划线的_.isEmpty
's。
哪种方式更干净?还有其他方法我可能错过了吗?
答案 0 :(得分:3)
个人偏好不会覆盖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
会在某些/所有模型中使用,因此可以适当修改。