Marionette.js NoMethodError:在控制器上找不到方法'xxx',但它就在那里

时间:2013-01-29 20:51:04

标签: backbone.js marionette

我收到错误:NoMethodError:控制器上找不到方法'go_start'

函数go_start只在我的项目中的两个位置(我搜索过): StartRouter.js

define(['marionette'], function(Marionette) {
  'use strict';

  var StartRouter = {};

  StartRouter.Router = Marionette.AppRouter.extend({
    appRoutes: {
        "start": "go_start"
    }
  });

  return StartRouter;
});

和StartController.js

define(['underscore', 'marionette', 'app/vent',
    'text!templates/StartLayout.html',     'views/InspectorStartView','views/InspectorStartView'],
function(_, Marionette, vent, layout, InspectorStartView, PlayerStartView) {
'use strict';

// public module API
var Controller = {};

// private
var Layout = Marionette.Layout.extend({
    template: _.template(layout),

    regions: {
        inspector: "#inspector_choice",
        player: "#player_choice"
    }
});

// private
var _initializeLayout = function() {
    console.log('initializeLayout...');
    Controller.layout = new Layout();
    Controller.layout.on("show", function() {
        vent.trigger("layout:rendered");
    });
    vent.trigger('app:show', Controller.layout);
};

// controller attach a sub view/ search View
vent.on("layout:rendered", function() {
    console.log('layout:rendered =>StartController');

    // render views for the existing HTML in the template, and attach it to the layout (i.e. don't double render)
    var inspectorStartView = new InspectorStartView();
    Controller.layout.inspector.attachView(inspectorStartView);

    var playerStartView = new PlayerStartView();
    Controller.layout.player.attachView(playerStartView);
});

    // controller show inspector in the layout / subview
    vent.on('show:inspector', function(inspectorStartView) {
        // console.log('show books event');
        Controller.layout.inspector.show(inspectorStartView);
    });

    // controller show inspector in the layout / subview
    vent.on('show:player', function(playerStartView) {
        // console.log('show books event');
        Controller.layout.inspector.show(playerStartView);
    });


// public API
Controller.go_start = function(term) {   **//<-- function go_start**
    _initializeLayout();
    //vent.trigger("search:term", term);
};

return Controller;

真正奇怪的是,Crome显示了App.js第77行发生的错误:

app.addInitializer(function(options) {
    // configure for loading templates stored externally...
    Backbone.Marionette.TemplateCache.prototype.loadTemplate = function(templateId) {
        // Marionette expects "templateId" to be the ID of a DOM element.
        // But with RequireJS, templateId is actually the full text of the template.
        var template = templateId;

        // Make sure we have a template before trying to compile it
        if (!template || template.length === 0) {
            var msg = "Could not find template: '" + templateId + "'";
            var err = new Error(msg);
            err.name = "NoTemplateError";
            throw err;
        }

        return template;
    };

    // Connect controllers to its router via options
    // init router's router/controller
    new options.router.Router({
        controller: options.homeController
    });

    // init loginRouter's router/controller
    new options.loginRouter.Router({
        controller: options.loginController
    });
    // init helpRouter's router/controller
    new options.helpRouter.Router({
        controller: options.helpController  //<-- Line 77
    });
    // init startRouter's router/controller
    new options.startRouter.Router({
        controller: options.startController
    });
    // init inspectorRouter's router/controller
    new options.inspectorController.Router({
        controller: options.inspectorController
    });
    // init playerRouter's router/controller
    new options.playerRouter.Router({
        controller: options.playerController
    });
});
// export the app
return app;
});

帮助路由器和控制器:

// HelpRouter.js
define(['marionette'], function(Marionette) {
'use strict';

var HelpRouter = {};

HelpRouter.Router = Marionette.AppRouter.extend({
    appRoutes: {
        "help": "go_help"
    }
});

return HelpRouter;
});

<!-- routes/HelpController.js -->
define(['underscore', 'marionette', 'app/vent',     'text!templates/HelpLayout.html'],
function (_, Marionette, vent, layout) {
    'use strict';

    // public module API
    var Controller = {};

    // private
    var Layout = Marionette.Layout.extend({
        template: _.template(layout),

        regions: {
            faq: "#"
        }
    });

// private

var _initializeLayout = function () {
console.log('initializeLayout...');
Controller.layout = new Layout();
Controller.layout.on("show", function () {
    vent.trigger("layout:rendered");
});
vent.trigger('app:show', Controller.layout);
};


// public API

Controller.go_help = function () {
     _initializeLayout();
};

return Controller;
});

任何人都能看到我做错了什么? 这是我认为不会发生的事情:

// Includes Desktop Specific JavaScript files here (or inside of your Desktop router)
require(["app/App",
    "routers/HomeController",       "routers/StartController",  "routers/LoginController",
    "routers/InspectorController",  "routers/PlayerController", "routers/HelpController",
    "routers/DesktopRouter",        "routers/LoginRouter",      "routers/StartRouter",
    "routers/InspectorController",  "routers/PlayerController", "routers/HelpRouter" ],
function(App,
       HomeController, StartController, LoginController, InspectorController, PlayerController, HelpController,
       DesktopRouter, LoginRouter, HelpRouter, StartRouter, InspectorRouter, PlayerRouter) {

  var options = {
      homeController:       HomeController,
      startController:      StartController,
      loginController:      LoginController,
      helpController:       HelpController,

      inspectorController:  InspectorController,
      playerController:     PlayerController,

      router:               DesktopRouter,
      startRouter:          StartRouter,
      loginRouter:          LoginRouter,
      helpRouter:           HelpRouter,

      inspectorRouter:      InspectorRouter,
      playerRouter:         PlayerRouter

  };

  App.start(options);
});

所以我需要所有的路由器和控制器,但是当我在调试器中运行该代码时,我有一些未定义的项目:

options: Object
helpController: Object
helpRouter: Object
homeController: Object
go_home: function () {
__proto__: Object
inspectorController: undefined
inspectorRouter: undefined
loginController: Object
loginRouter: Object
playerController: undefined
playerRouter: Object
router: Object
Router: function (){ parent.apply(this, arguments); }
__proto__: Object
startController: Object
go_start: function (term) {
__proto__: Object
startRouter: undefined
__proto__: Object
HomeController: Object
StartController: Object
StartRouter: undefined
DesktopRouter: Object
InspectorController: undefined

为什么有些未定义? StartRouter和StartController具有go_start函数。 HelpRouter / Controller不会也不应该有go_start,但它会抛出错误

欢迎所有建议。

安德鲁

2 个答案:

答案 0 :(得分:2)

看起来您的RequireJS导入无序。 HelpRouter变量映射到"routers/StartRouter"模块,所有后续模块都是一个接一个。

AMD导入格式很容易导致这种类型的简单错误,这些错误可能需要很长时间才能调试,因为这在某种程度上是您从未想过的地方。这就是为什么我更喜欢RequireJS提供的simplified CommonJS wrapper syntax

define(function(require) {
  var HomeController  = require('routers/HomeController'),
      StartController = require('routers/StartController'),
      //etc...
});

答案 1 :(得分:0)

对于那些刚刚调整的人来说,这是fencliff提出的工作解决方案。

// Includes Desktop Specific JavaScript files here (or inside of your Desktop router)
define(function(require) {
  var App = require("app/App"),
        // Routers with its controller
        DesktopRouter       = require("routers/DesktopRouter"),
        HomeController      = require("routers/HomeController"),

        StartRouter         = require("routers/StartRouter"),
        StartController     = require("routers/StartController"),

        LoginRouter         = require("routers/LoginRouter"),
        LoginController     = require("routers/LoginController"),

        InspectorRouter     = require("routers/InspectorRouter"),
        InspectorController = require("routers/InspectorController"),

        PlayerRouter        = require("routers/PlayerRouter"),
        PlayerController    = require("routers/PlayerController"),

        HelpRouter          = require("routers/HelpRouter"),
        HelpController      = require("routers/HelpController");

  var options = {
      homeController:       HomeController,
      router:               DesktopRouter,

      startController:      StartController,
      startRouter:          StartRouter,

      loginController:      LoginController,
      loginRouter:          LoginRouter,

      inspectorController:  InspectorController,
      inspectorRouter:      InspectorRouter,

      playerController:     PlayerController,
      playerRouter:         PlayerRouter,

      helpController:       HelpController,
      helpRouter:           HelpRouter

  }
  App.start(options);
  return function() {};
});

我对返回一个空函数有点不确定,但这是我看到的唯一例子,它有效。 :-D