如何在Durandal中为shell viewmodel使用类?

Jud*_*her 5 javascript typescript durandal

我正在查看Hot Towel模板,并试图让它在TypeScript中工作,我遇到了转换shell viewmodel的问题.我正在尝试将其转换为TS,对我来说更有意义的是它应该是一个类,而不是简单地导出这里所示的函数.我看了这种方法,但是,注意这里的评论,决定不遵循它.

经过一些挖掘后,我找到了这个线程,这表明它应该像重写一样简单router.getActivatableInstance,但我似乎无法远远地调用该函数.

这是我的main.ts(也包括在课堂上):

/// <reference path="dts/toastr.d.ts" />
/// <reference path="dts/durandal.d.ts" />
/// <reference path="dts/require.d.ts" />

import _app = module('durandal/app');
import _system = module('durandal/system');
import _viewLocator = module('durandal/viewLocator');
import _router = module('durandal/plugins/router');
import _logger = module('services/logger');

export class HOPS {

    public init(): void {
        _logger.log('init', this, 'HOPS', false);
        _system.debug(true);
        this._startApp();
    }

    private _startApp(): void {
        _logger.log('_startApp', this, 'HOPS', false);

        _app.start().then(() => {
            toastr.options.positionClass = 'toast-bottom-right';
            toastr.options.backgroundpositionClass = 'toast-bottom-right';

            var defImpl = _router.getActivatableInstance; //default Implementation

            _router.getActivatableInstance = function (routeInfo: _router.routeInfo, paramaters: any, module: any) {
                var functionName = routeInfo.name.substring(0, 1).toUpperCase() + routeInfo.name.substring(1);
                if (typeof module [functionName] == 'function') {
                    var instance = new module [functionName]();
                    instance.__moduleId__ = module.__moduleId__;
                    return instance;
                }
                else return defImpl(routeInfo, paramaters, module );
            }

            _router.handleInvalidRoute = (route: _router.routeInfo, paramaters: any) => {
                _logger.logError('No Route Found', route, 'main', true);
            }

            _router.useConvention();
            _viewLocator.useConvention();

            _app.adaptToDevice();

            _app.setRoot('viewmodels/shell', 'entrance');
        });
    }
}

var hops: HOPS = new HOPS();
hops.init();
Run Code Online (Sandbox Code Playgroud)

(游乐场在这里展示JS:http://bit.ly/WyNbhn)

......这是我的shell.ts:

import _system = module('durandal/system');
import _router = module('durandal/plugins/router');
import _logger = module('services/logger');

export class Shell{

    public router = _router;

    public activate(): JQueryPromise {
        _logger.log("activate", null, 'shell', false);
        return this.boot();
    }

    public boot(): JQueryPromise {
        _logger.log("boot", null, 'shell', false);
        this.router.mapNav('home')
        this.router.mapNav('details');
        _logger.log('SciHops SPA Loaded!', null, _system.getModuleId(this), true);
        return this.router.activate('home');
    }
}
Run Code Online (Sandbox Code Playgroud)

...汇编到:

define(["require", "exports", 'durandal/system', 'durandal/plugins/router', 'services/logger'], function(require, exports, ___system__, ___router__, ___logger__) {
    /// <reference path="../dts/_references.ts" />
    var _system = ___system__;

    var _router = ___router__;

    var _logger = ___logger__;

    var shell = (function () {
        function shell() {

            this.router = _router;
        }
        shell.prototype.activate = function () {
            _logger.log("activate", null, 'shell', false);
            return this.boot();
        };
        shell.prototype.boot = function () {
            _logger.log("boot", null, 'shell', false);
            this.router.mapNav('home');
            this.router.mapNav('details');
            _logger.log('SciHops SPA Loaded!', null, _system.getModuleId(this), true);
            return this.router.activate('home');
        };
        return shell;
    })();
    exports.shell = shell;    
})
Run Code Online (Sandbox Code Playgroud)

使用上面的类,我得到一个绑定错误,因为router未定义.如果我添加export var router = _router然后这个bug消失了,但我的shell类的activate方法永远不会被调用.

所有上述方法都适用于后续的视图模型,但只是落在shell上.

我做错了什么,如何让TS类作为我的shell Durandal viewmodel工作?

Eva*_*sen 4

问题是您的路由器无法解析您的shell.ts模块。

所有其他视图模型都通过该router.getActivatableInstance方法传递并被实例化并附__moduleId__加到它们。除了你的shell.ts模块。

这是让shell.ts模块正常工作的一种快速但肮脏的方法。

在你的内部main.ts你可以需要你的shell.ts模块:

import _shell = module('shell');
Run Code Online (Sandbox Code Playgroud)

然后,仍然在您的内部,main.ts您可以实例化您的shell类并为其分配 moduleId。

var shell = new _shell.Shell();
shell.__moduleId__ = _shell.__moduleId__;
_app.setRoot(shell, 'entrance');
Run Code Online (Sandbox Code Playgroud)

这不是你见过的最漂亮的东西。但它完成了工作。这与您所做的覆盖几乎相同getActivatableInstance。因为您的 shell 没有通过router.js模块,所以您必须手动执行此操作。