backbone.js - Konvertering av Backbone-strukturer til TypeScript


Når man ser på Backbonejs sin implementering av extend-funksjonen, viser det seg at det ikke er en grunnleggende prototypeutvidelse, og når backbone-utvidelser konverteres direkte til TypeScript-klasser, slutter noen ting å fungere. Hva er den riktige måten å konvertere hver komponent av Backbonejs (Model, Collection, Route, View, History) til en TypeScript-klasse på og sørge for at ingenting brytes?

Takk!

Oppdatering: Svaret i denne spørsmål/svar-delen kan også fungere for andre kjerneoppsett.

Svar #1

Dette er fordi koden generert av TypeScript først kaller Router-konstruktøren og deretter erklærer rutene.

Kode generert av TypeScript-kompilatoren

...
function AppRouter() {
    _super.apply(this, arguments);

    this.routes = { // <= routes defined after _super constructor
        "*actions": "defaultRoute"
    };
}
...

For å fikse dette, kall bare Backbone Router-funksjonen _bindRoutes() på TypeScript-objektets konstruktør.

Eksempel :

class AppRouter extends Backbone.Router {
    routes = {
        "*actions": "defaultRoute"
    }

    constructor(){
        super();
        // call _bindRoutes() here function to bind your routes
        (<any>this)._bindRoutes();
    }

    defaultRoute() {
        document.write("Default Route Invoked");
    }
}

var app_router = new AppRouter();

Backbone.history.start();

Last ned et eksempel på kode her

Svar #2

Oppdatert løsning for Backbone 1.4+

I 2019 (Backbone 1.4.0) ble en preinitialize-metode lagt til for alle Backbone-objekter, inkludert Routeren. PR-en har mer bakgrunnsinformasjon.

Dette er nyttig for ES6-klasser og TypeScript.

Her er et eksempel fra dokumentasjonen:

class Router extends Backbone.Router {
  preinitialize() {
    // Override execute method
    this.execute = function(callback, args, name) {
      if (!loggedIn) {
        goToLogin();
        return false;
      }
      args.push(parseQueryString(args.pop()));
      if (callback) callback.apply(this, args);
    }
  }
}

Du kan også definere disse som getters, men strategien ovenfor har mindre friksjon med den nåværende @types/backbone, som ikke har typer for noen paths som getters, selv om de teknisk sett fortsatt fungerer med ES6.