Durandal:多个路由,一个ViewModel / View

时间:2013-05-14 02:20:27

标签: durandal hottowel

我有3条路线:items / one,items / two和items / 3,它们都指向'items'vm / 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');
}

这一切都有效,我在视图上得到了正确的过滤器。但是,我注意到如果我在“一个”上,然后转到“二个”,那么ko-bound变量会在'实时'中更新,也就是说,当它们发生变化时,在激活之前promise解析,导致转换发生两次(因为数据被抓取,并且在activate函数返回后)。

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

2 个答案:

答案 0 :(得分:1)

我能够通过在包含div的项目上使用ko.cleanNode()导航之前删除ko绑定来解决问题。

答案 1 :(得分: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;
};