在Backbone视图上没有方法`apply`

时间:2012-06-16 19:07:12

标签: javascript backbone.js coffeescript

我一直试图在我的(相当简单的)Backbone / Coffeescript代码中找到一个奇怪的错误。

运行我的应用程序时,出现此错误:

Uncaught TypeError: Object #<IndexView> has no method 'apply' 

这是我的路由器:

class window.App.Router extends Backbone.Router
    initialize: ->
        Backbone.history.start({pushState: true})
        $(document).on "click", "a:not([data-bypass])", (evt) ->
            href = $(this).attr "href"
            protocol = this.protocol + "//"
            if href.slice(protocol.length) != protocol
                evt.preventDefault()
                App.navigate(href, true)

    routes: {
        "": "index",
        "artist/:id": "artist",
        "albums/:id": "album"
    }

    index:
        @view = new App.IndexView()

观点:

class App.IndexView extends Backbone.View
    template: "index"
    el: $("#container")

    initialize: ->
        @render()

    render: ->
        get_template(@el, @template, @domEvents)

    domEvents: ->
        $("#searchInput").on "change keydown", ->
            if $(this).val().length >= 0
                $("#placeholder").css("display", "none")
            else
                $("#placeholder").css("display", "inline-block")

从我的测试中看来,一旦我摆脱代码的Backbone.history.start({pushState: true})行,这个错误就会消失。不幸的是我的应用程序需要pushState,所以摆脱这个不是一个选项。

有没有人对这里的错误有任何想法?

1 个答案:

答案 0 :(得分:2)

在路由器中定义->时,您错过了index

class window.App.Router extends Backbone.Router
    #...
    index:
        @view = new App.IndexView()

结果是new App.IndexView()类在构建App.Router类时执行,index成为new App.IndexView()的值;此外,在此上下文中@是类本身,因此您最终设置App.Router.view = new App.IndexView()。 JavaScript看起来像这样:

Router.prototype.index = Router.view = new IndexView();

然后,因为你的路线:

routes: {
    "": "index",
    #...
}

路由系统尝试将router.index作为函数调用(使用Function.apply来确保适当的调用上下文)以响应路由请求;但是router.index是一个视图实例而不是函数/方法,所以你得到了错误:

Uncaught TypeError: Object #<IndexView> has no method 'apply' 

因为您无法在视图实例上调用apply

据推测,您的Backbone.history.start({pushState: true})会触发初始路由到index

因此,请修改您的类定义,将index定义为方法,然后重试。


顺便说一下,在路由器的Backbone.history.start({pushState: true})内调用initialize有点奇怪。 usual process is to call start after your routers have been created

  

如果已创建所有路由器并且所有路由都已正确设置,请致电Backbone.history.start()以开始监控hashchange个事件并调度路径。

因此可能在所有路由正确设置并准备好之前启动历史记录系统。这可能会导致一些奇怪的事情发生。