DurandalJS - 在页面根目录上执行完全激活周期(aka:fire"取消激活"在app.setRoot()上)

时间:2014-06-11 22:11:14

标签: javascript single-page-application durandal-2.0 durandal-navigation

[编辑]还有Google网上论坛帖子over here。在我了解更多内容时,我会尽量保持更新。

根据Durandal Documentation页面,Root View Model仅实现有限的Activator功能。具体而言,它声明:

  

...

     

4)当您调用app.setRoot时,在您的根模块上使用(有限的)激活器。

     

注意:案例4略有不同,因为它只强制执行canActivate并激活回调;不是停用生命周期。要启用它,您必须自己使用完整的激活器(例1-3)。

这意味着与所有嵌套页面ViewModel不同,root用户没有机会处理他们的垃圾对象并进行清理。

什么是友好的解雇方法当我调用app.setRoot()时,可以对这些对象进行取消激活和取消激活?我也许可以手动执行此操作,但我需要引用根ViewModel,这不一定在范围内。

我考虑过创建一个类型的发布/订阅系统,虽然我对此感到厌倦,因为它有可能导致更多的内存问题和清​​理复杂性,而不是减少它。

我考虑过要求这个项目,虽然这会带来一些沉重的开销,因为我不得不从那时起维护我的叉子。

[编辑]

示例:

让我们说我要开始我的应用程序并将shell设置为" main"外壳

  app.start().then(function () {
      app.setRoot('views/shells/main');
  })

稍后,我希望切换到新的shell。也许是不同的布局,全屏或不同的皮肤。

 app.setRoot('views/shells/accounts');

这将导致shell" accounts"检查和/或激活激活和canActivate,但它不会检查shell" main" for canDeactivate和deactivate。我有清理逻辑,我想在它们消失时运行。我怎么能做到这一点?

[编辑]

durandal代码部分处理这是一个本地函数,生活在模块&durandal / app' setRoot()finishComposition()看起来像这样

  function finishComposition() {
            if(settings.model) {
                if (settings.model.canActivate) {
                    try {
                        var result = settings.model.canActivate();
                        if (result && result.then) {
                            result.then(function (actualResult) {
                                if (actualResult) {
                                    composition.compose(hostElement, settings);
                                }
                            }).fail(function (err) {
                                system.error(err);
                            });
                        } else if (result) {
                            composition.compose(hostElement, settings);
                        }
                    } catch (er) {
                        system.error(er);
                    }
                } else {
                    composition.compose(hostElement, settings);
                }
            } else {
                composition.compose(hostElement, settings);
            }
        }

也许有一种方法来修补这个?如果可能的话,我想避免编辑Durandal的核心。

1 个答案:

答案 0 :(得分:1)

您实际上不必实现多个shell。我们一开始也看了这个。你可以有一个shell,然后立即动态地组成一个内壳。内部shell可以与动态组合交换,这仍然可以保留您的高级路由。换句话说,没有必要让每个视图成为子路径。

换句话说,以下是两个级别,而不是一个:

data-bind="router: { model: router.activeItem, cacheViews:false, compositionComplete: router.compositionComplete, attached: router.attached }">

这将被移入内壳:

<div data-bind="compose: {model: currentShell()}"></div>

其中currentShell()是一个包含当前shell的observable(在“super shell”的viewModel中)。