how to write marionettejs module using typescript?

2019-05-28 21:42发布

问题:

I'm trying to write MarionetteJS module using Typescript. Compiled module should be added to plain javascript application using RequireJS and initialized as normal Marionette module i.e.:

define(
['marionette', 'modules/sample/sample'],
function (Marionette, Sample) {
    var sampleApp = new Backbone.Marionette.Application();
    sampleApp.SampleModule = sampleApp.module("SampleModule", Sample.Sample);
}

My module is created, but initializer and start functions are not being called by Marionette.Appplication.

This is my TypeScript class:

/// <amd-dependency path="backbone" />
/// <amd-dependency path="marionette" />
/// <amd-dependency path="jquery" />
/// <amd-dependency path="underscore" />
/// <reference path="../../vendor/ts/backbone/backbone.d.ts" />
/// <reference path="../../vendor/ts/marionette/marionette.d.ts" />
/// <reference path="../../vendor/ts/jquery/jquery.d.ts" />
/// <reference path="../../vendor/ts/underscore/underscore.d.ts" />

export class Sample{

    constructor(public self:Marionette.Module, public app:Marionette.Application, public Backbone:Backbone, public Marionette:Marionette, public $:"jquery", public _:"underscore") {
        console.log("Sample.constructor");
        self.addInitializer(this.init);
    }

    init(options?:any) {
        console.log("Sample.init!");
    }

    start() {
        console.log("Sample.start");
    }

}

That code compiles to:

define(["require", "exports", "backbone", "marionette", "jquery", "underscore"], function(require, exports) {
    var Sample = (function () {
        function Sample(self, app, Backbone, Marionette, $, _) {
            this.self = self;
            this.app = app;
            this.Backbone = Backbone;
            this.Marionette = Marionette;
            this.$ = $;
            this._ = _;
            console.log("Sample.Sample!!!! %o %o", self, app);
            self.addInitializer(this.init);
        }
        Sample.prototype.init = function (options) {
            console.log("Sample.Sample.init!");
        };

        Sample.prototype.start = function () {
            console.log("Sample.Sample.start");
        };
        return Sample;
    })();
    exports.Sample = Sample;
});

while simple module written in javascript looks like that:

define(['text!./tpl.html'], function (tpl) {
    var Generic = function (self, app, Backbone, Marionette, $, _) {
        self.addInitializer(function (options) {
            console.log('Generic initialized %o', options);
        };
    };
    return Generic;
});

Can i write MarionetteJS module using Typescript? Does anyone has some examples? Any help appreciated.

Thanks

回答1:

   class FoobarView extends Marionette.ItemView<Backbone.Model> {

        constructor(options?:any) {

            _.extend(options, {
               template: some_template_retriever_function('templatePath.html'),
               className: 'class-name'
            });

            this.behaviors = <any>{
                'somebehaviors' : {},
            };

            super(options);
        }

        serializeData():any {

        }

        show():void {
        }


    }

    export = FoobarView;

This will produce a module, after compiling, that can be imported directly to anything you name it

import FooBarView = require('Path/to/FoobarView');

// now you can instantiate this view

var view = new FooBarView({some:options});

of course, remember your typings reference at the top

/// <reference path="../../vendor/ts/marionette/marionette.d.ts" />    


回答2:

Old Question, anyway, using TypeScript 2, requireJS, after several attempts & errors I made it work. But before I list all the things I've done, I have to comment out your first code snippet that was

define(
   ['marionette', 'modules/sample/sample'],
   function (Marionette, Sample) {
      var sampleApp = new Backbone.Marionette.Application();
      sampleApp.SampleModule = sampleApp.module("SampleModule", Sample.Sample);
}

I do not agree with this, because you define a module using requireJS (using require.define and Marionette.Module In my opinion, you should use either one of both, not both... as I would use requireJS to define a module, I would write your code snippet as

define("SampleModule",
   ['marionette', 'modules/sample/sample'],
   function (Marionette, Sample) {
      return new Backbone.Marionette.Application();          
}

That being said, here's how I did it work Assuming you have a require.config that aliases marionette library like this

// file : require-config.ts 
require.config({
   paths: {
      "marionette" : "https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/3.2.0/backbone.marionette"
      // + all the other 3rd party JS libraries
   }
});

about your definition TS file for marionette, either, you define your own, either you use npm install --save @types\backbone.marionette.

for the record, as my project relies on an older version of backbone.marionette, I had to write it on my own, based on what has been defined on the return of such npm command using npm command, there's also some extra work to make it work-but that's defitiely not the purpose here Once you've done this, you can write your sample module as is

// file : SampleModule.ts
/// <amd-module name="SampleModule" />
import marionette = require("marionette");
export = new marionette.Application();

The transpiled Javascript code is

// file : SampleModule.js (transpiled code)
define("SampleModule", ["require", "exports", "marionette"], 
function(require, exports, marionette) {
    "use strict";
    return new marionette.Application();
});

and that's it-it looks the same as what is written if we have coded in JS