Javascript 使用多个视图高效构建大型React.js应用程序
我有一个react应用程序,具有多个视图(例如,Javascript 使用多个视图高效构建大型React.js应用程序,javascript,reactjs,reactjs-flux,Javascript,Reactjs,Reactjs Flux,我有一个react应用程序,具有多个视图(例如,Profile,Followers)。这些视图中的每一个当前都作为自己的React组件存在,该组件在服务器端和客户端都执行。我开始努力理解构造代码的正确方法 例如,假设加载了Profile,用户单击“查看关注者”。此时,调度器会收到一条消息,上面写着gotoFollowers。在顶层,我们然后呈现一个全新的React组件(即Followers组件)。不幸的是,Follower和Profile组件都需要类似的数据(例如会话数据、用户照片、用户名,甚至
Profile
,Followers
)。这些视图中的每一个当前都作为自己的React组件存在,该组件在服务器端和客户端都执行。我开始努力理解构造代码的正确方法
例如,假设加载了Profile
,用户单击“查看关注者”。此时,调度器会收到一条消息,上面写着gotoFollowers
。在顶层,我们然后呈现一个全新的React组件(即Followers
组件)。不幸的是,Follower
和Profile
组件都需要类似的数据(例如会话数据、用户照片、用户名,甚至followers,因为我们在概要文件上显示了一段followers)。因此,每次用户更改页面时都必须在顶层重新呈现(包括进行ajax调用),这感觉非常浪费
我想我做得不对。我应该使用单亲组件吗?(我也看到了这方面的问题)我应该如何构造具有多个视图的大型React应用程序
window.render = function (page, id, pushState) {
var stateURL = '';
switch (page) {
case 'Profile':
stateURL = '/' + id;
async.parallel({
profileData: function (callback) { MemberLoader.load(id, callback); },
followerData: function (callback) { FollowerLoader.load(id, callback); },
},
sessionData: function (callback) { Session.get(callback); },
}, function (err, results) {
var component = React.createFactory(Profile);
React.render(component({ member: results.profileData, followers: results.followerData, session: results.sessionData }), mountNode);
});
break;
case 'Followers':
stateURL = '/' + id + '/followers';
async.parallel({
profileData: function (callback) { MemberLoader.load(id, callback); },
sessionData: function (callback) { Session.get(callback); },
followerData: function (callback) { FollowerLoader.load(id, callback); },
}, function (err, results) {
var component = React.createFactory(Followers);
React.render(component({ member: results.profileData, followers: results.followerData, session: results.sessionData }), mountNode);
});
break;
};
if (pushState) {
window.history.pushState({ page: page, id: id }, null, stateURL);
} else {
window.history.replaceState({ page: page, id: id }, null, stateURL);
}
};
Dispatcher.register(function(event) {
if (event.action === 'gotoProfile') {
window.render('Profile', event.username, true);
}
else if (event.action === 'gotoFollowers') {
window.render('Followers', event.username, false);
}
});
注意:我们的应用程序在服务器端和客户端都呈现 要解决多次获取相同数据的问题,您应该研究-这可能会取代您现在使用的async
lib
承诺允许您进行一次异步调用,但即使在调用成功后也会附加回调。您可以保留对承诺的引用,并在以后的应用程序中使用它,而无需检查承诺是否已得到解决
我在下面为您准备了一个(未经测试的)示例实现——它可以做一些事情
为每个数据存储创建对承诺的引用
创建一个方法,该方法返回异步调用(如果尚未进行),然后返回该承诺
将您的async.parallel
代码替换为Promise.all
,这将创建一个新的Promise,该Promise在成功解析所有传递的Promise后被解析
将您的React.render
放在对的调用中,然后在promise上执行
——这样,只有在所有异步调用完成后才会调用它
见下文:
var profilePromise;
var followerPromise;
var sessionPromise;
var getProfilePromise = function(){
//If the profile promise already exists (ie, the async call has already been started)
//then we return the promise, otherwise we make the async call.
if(!profilePromise){
profilePromise = new Promise(function(resolve, reject){
MemberLoader.load(id, function(){
//Depending on the result you either call `resolve` and pass
//in the data, or call `reject` with the error
});
});
}
return profilePromise;
};
//Repeat a version of the above function for your follower and session promise
window.render = function (page, id, pushState) {
var stateURL = '';
switch (page) {
case 'Profile':
stateURL = '/' + id;
Promise.all([
getProfilePromise(),
getFollowerPromise(),
getSessionPromise()
]).then(function(results){
var component = React.createFactory(Profile);
React.render(component({ member: results[0], followers: results[1], session: results[2] }), mountNode);
}).catch(function(err){
/** handle errors here */
});
break;
case 'Followers':
stateURL = '/' + id + '/followers';
Promise.all([
getProfilePromise(),
getFollowerPromise(),
getSessionPromise()
]).then(function(results) {
var component = React.createFactory(Followers);
React.render(component({ member: results[0], followers: results[1], session: results[2] }), mountNode);
}).catch(function(err){
/** handle errors here */
});
break;
}
if (pushState) {
window.history.pushState({ page: page, id: id }, null, stateURL);
} else {
window.history.replaceState({ page: page, id: id }, null, stateURL);
}
};