我正在使用Durandal 2.0构建一个应用程序。
我的外壳视图如下所示:
<div>
<header id="nav" data-bind="compose: 'viewmodels/nav', activate: false">
</header>
<section id="content" class="main container-fluid" data-bind="router: { transition: 'entrance' }, activate: false" style="overflow: auto">
</section>
<footer>
<!--ko compose: {view: 'footer'} --><!--/ko-->
</footer>
</div>
在导航部分中,我希望拥有我的选项卡和用户下拉列表(两者都是从 Web 服务检索的)。 从下拉列表中选择用户将导航到将更新内容部分的新 URL。 (路由看起来像 localhost/#user1/tab2)。
- 问题:我需要先从导航部分知道所选用户,然后才能检索内容部分的数据,但内容部分在检索用户之前正在激活。
这实际上只是初始页面加载的问题,因为用户列表只检索一次。
- 有没有办法告诉内容部分等到导航部分加载完成?
- 有没有比我正在做的事情更好的方法?
导航激活函数如下所示:
function activate(context) {
return dataservice.getUsers().then(function () {
//do stuff
});
});
首先调用此激活函数,并调用 dataservice.getUsers(),但随后在"执行操作"部分发生之前(以及在数据服务中返回来自 getUsers 调用的数据之前)调用内容模块的激活函数。 也许我的承诺有问题?
编辑
我用一些实际的代码整理了一个dFiddle,显示了我在说什么:http://jerrade.github.io/dFiddle-2.0/#test/dashboard
代码在这里:https://github.com/jerrade/dFiddle-2.0
导航.js
function activate(context) {
console.log('Nav View Activated');
if (vm.impersonateUsername == undefined)
vm.impersonateUsername = getUsernameFromWindowLocation();
return dataservice.getPageDetailForEmployee(vm.loggedInUsername, vm).then(function () {
console.log("Page details retrieved");
// I want to do something here before the dashboard activates.
});
}
仪表板.js
function activate(username) {
console.log('Dashboard View Activated');
//vm.username = nav.selectedImpersonateEmployee().Username;
return dataservice.getDashboard(nav.impersonateUsername, dashboard);
}
打开页面并观看控制台。 您将看到(除其他内容外)
Nav View Activated
Dashboard View Activated
Page details retrieved
我真正想要的是在激活仪表板视图之前检索页面详细信息。 我实际上已经重新调整了东西,以便目前这不再是问题,但它可能会再次裁剪。
似乎我想做的事情不应该这么复杂。 除非我在这里把一个方形钉子敲成圆孔?
方法是在视图模型上添加一个名为isUserLoaded
的可观察量。然后,在内容部分周围应用if
绑定:
<div>
<header id="nav" data-bind="compose: 'viewmodels/nav', activate: false">
</header>
<!-- ko if: isUserLoaded -->
<section id="content" class="main container-fluid" data-bind="router: { transition: 'entrance' }, activate: false" style="overflow: auto">
</section>
<!-- /ko -->
<footer>
<!--ko compose: {view: 'footer'} --><!--/ko-->
</footer>
</div>
加载用户后,可以将可观察量更新为true
内容绑定应触发。
编辑
如果这不起作用,听起来您的路由器必须仍在解析内容视图模型(这可能指向路由问题?很难说没有看到你的整个解决方案)。
无论如何,如果不是路由问题,那么您可以采用一种解决方案,其中内容模型从其激活方法返回未解析的承诺;然后在加载用户时解决该承诺。例如,类似这些内容:
用户型号.js:
define([], function () {
// single instance to track the loaded user
var userModel = {
selectedUser: ko.observable()
};
return userModel;
});
导航型号.js:
define(["dataService", "userModel"], function(dataService, userModel) {
// view model for the nav bar
var navModel = {
// model definition
};
// load the user
navModel.activate = function() {
return dataService.getUsers().then(function(response) {
// Push the user to the userModel
userModel.selectedUser(response.user);
});
};
return navModel;
});
内容型号.js:
define(["userModel"], function (userModel) {
var contentModel = {
// model definition
};
contentModel.activate = function () {
// Prevent activation until user is resolved
var deferred = $.Deferred();
var subscription = userModel.selectedUser.subscribe(function (user) {
if (!user)
return;
subscription.dispose();
deferred.resolve();
});
return deferred.promise();
};
return contentModel;
});
如果您不想对 userModel.selectedUser
属性使用可观察量,则可以改用另一个延迟,或者在加载用户时触发事件等。