2013-05-14 94 views
1

我有3条路线:items/one,items/two和items/three,它们都指向'items'vm/view。Durandal:Multiple Routes,One ViewModel/View

在items.js

激活功能,我检查的网址,并此基础上,我改变了一个过滤器:

function activate(r) { 
     switch (r.routeInfo.url) { 
      case 'items/one': vm.filterType(1); break; 
      case 'items/two': vm.filterType(2); break; 
      case 'items/three': vm.filterType(3); break; 
     } 
     return init(); //returns a promise 
    } 

项目视图与按钮的菜单一,二,和三个。 每个按钮链接到一个这样的动作:

function clickOne() { 
    router.navigateTo('#/items/one'); 
} 
function clickTwo() { 
    router.navigateTo('#/items/two'); 
}  
function clickThree() { 
    router.navigateTo('#/items/three'); 
} 

这一切工作,我得到的观点正确的过滤器。但是,我注意到,如果我在'one',然后转到'two',那么ko-bound变量会'实时'更新,也就是说,当它们在变化时,并且在激活之前承诺解决,这导致转换发生两次(当数据被抓取,并在激活函数返回后)。

这只发生在这种情况下,其中view和viewmodel与前一个相同。我知道这是一种特殊情况,路由器可能正在用areSameItem = true处理新路由的加载。我可以将虚拟机/视图分成三部分,并尝试从基本模型继承,但我希望获得更简单的解决方案。

+0

它调用你的'activate'函数吗? 'filterType()'返回一个承诺? – Tyrsius 2013-05-14 03:11:53

+0

当路由器导航到视图/虚拟机时,激活函数被框架(Durandal)自动调用。 filterType只是一个带有整数值的ko.observable。 – 2013-05-14 03:27:50

+0

好的,所以当你设置'filterType'时会触发一个动画?这是来自订户吗?您可能希望将其作为init()的一部分,以便它返回的承诺适用于这两种情况。 – Tyrsius 2013-05-14 03:44:20

回答

1

我能够通过使用包含分区项目ko.cleanNode()导航之前简单地移除KO绑定解决问题。

+0

很高兴知道。我必须在下次碰到它时尝试。 – RainerAtSpirit 2013-05-15 15:01:26

+0

你在哪里叫cleanNode?你是否需要重新添加绑定? – Ely 2013-06-06 04:21:23

+0

@Ely我在'router.navigateTo(...)'之前调用了它,例如,如果我的div被称为items,我会调用'var items = $('#items')[0]; ko.cleanNode(项目);' – 2013-06-07 08:04:35

0

假设在您的父视图中,您已参考router.activeItem并使用transition(例如,

<!--ko compose: {model: router.activeItem, 
    afterCompose: router.afterCompose, 
    transition: 'entrance'} --> 
<!--/ko--> 

然后入口过渡发生在您设置的每条路线上以过滤当前视图。

但是这种转换应该只在第一次访问时发生,并且从那一刻起只有视图应该使用过滤的数据进行更新。一种方法是设置一个可观察的filterType并使用filterType.subscribe用skip参数调用router.navigateTo。沿线

东西:

var filterType = ko.observable(); 

filterType.subscribe(function (val) { 
    // Create an entry in the history but don't activate the new route to prevent transition 
    // router plugin expects this without leading '/' dash. 
    router.navigateTo(location.pathname.substring(1) + '#items/' + filterType(), 'skip'); 
    activate(); 
}); 

请注意路由器插件预计skipRouteUrl,而不会导致/斜线比较context.path。 https://github.com/BlueSpire/Durandal/blob/master/App/durandal/plugins/router.js#L402

您的体验可能会有所不同。

末为了支持深层链接在activate

function activate(routerdata) { 
    // deep linking 
    if (routerdata && routerdata.filterType && (routerdata.filterType !== filterType())) { 
     filterType(routerdata.filterType); 
    } 

    return promise; 
}; 
+0

这是有效的,但正如你所说,现在过渡已经结束,与其他应用程序相比,这给人一种粗糙的体验。有没有办法添加过渡效果(即使它纯粹通过jQuery)?我尝试在KO模板中使用beforeRemove和afterAdd绑定,但这些似乎不起作用。 – 2013-05-14 09:05:03

+0

。例如'var isFetching = ko.observable(false)',你可以在'subscribe'中将它设置为'true'。在激活更改返回init()到$ .when(init())。然后(function(){self.isFetching(false)}); – RainerAtSpirit 2013-05-14 12:37:17

+0

下一次尝试: 您可能会考虑将'var isFetching = ko.observable(false)'添加到您的VM。通过在'subscribe'中将其设置为'true',您可以确定动画的起点。在'activate'中,而不是将promise改回'$ .when(promise).then(function(){...});'会让你将它设置回false。 – RainerAtSpirit 2013-05-14 12:52:43