0

[编辑]这里还有 Google Groups 主题。随着我了解更多,我会尽量保持更新。

根据Durandal 文档,页面根视图模型仅实现有限的激活器功能。具体来说,它指出:

……

4)当你调用 app.setRoot 时,你的根模块上会使用一个(有限的)激活器。

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

这意味着与所有嵌套页面 ViewModel 不同,根视图模型没有机会处理它们的垃圾对象并进行清理。

当我调用 app.setRoot() 时,在这些对象上触发 canDeactivate 和 deactivate 的友好方式是什么?我也许可以手动执行此操作,但我需要对根 ViewModel 的引用,它不一定在范围内。

我考虑过创建一个 pub/sub 系统,尽管我对此感到厌倦,因为它有可能导致更多的内存问题和清​​理复杂性而不是减少它。

我考虑过分叉这个项目,尽管这会带来一些沉重的开销,因为从那时起我必须维护我的分叉。

[编辑]

例子:

假设我要启动我的应用程序并将外壳设置为“主”外壳。

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

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

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

这将导致外壳“帐户”检查和/或触发激活和 canActivate,但它不会检查外壳“主”中的 canDeactivate 和停用。我有清理逻辑,希望在这些消失时运行。我怎样才能做到这一点?

[编辑]

处理的 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 的核心。

4

1 回答 1

1

您实际上不必实现多个 shell。我们一开始也看到了这一点。您可以拥有一个外壳,然后在其中立即动态地组成一个内壳。可以使用动态组合交换内壳,这仍将保留您的高级路由。换句话说,没有必要让每个视图都成为子路由。

换句话说,以下内容将位于两个级别,而不是一个级别:

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

这将被移入内壳:

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

wherecurrentShell()是一个保存当前 shell 的可观察对象(在“超级 shell”的 viewModel 内)。

于 2014-06-16T14:40:47.667 回答