从视图中正确使用Backbone listenTo;木偶地区未定义?

时间:2013-07-14 23:32:39

标签: events backbone.js marionette

这与我发布的另一个问题here有关,但它仍然令人难以置信。

我有一个简单的主干模型实例,名为searchResult,我在我的视野中工作得很好。

我基本上想做的事情很简单;在此模型更改时重置视图内的内容区域。

出于某种原因,当我在视图中时,这段代码似乎无法正常工作,虽然似乎它应该:

查看代码:

define [
      'backbone.marionette',
      "jquery",
      "underscore",
      "backbone",
      'text!globalTemplates/sidebar.html',
      "global/models/sidebar",
      "global/views/categories",
      "global/collections/categories",
      "global/views/stores",
      "global/collections/stores",
      'search/models/search-results'
    ], (Marionette, $, _, Backbone, SidebarTemplate, SidebarModel, categoriesView, categoriesCollection, storesView, storesCollection, SearchResult) ->
      class SidebarLayout extends Marionette.Layout

        template:                 _.template SidebarTemplate
        id:                       'sidebar'
        className:                'js-sidebar marionette-layout'
        tagName:                  'aside'

        regions:
          form:                   'form'
          categoriesList:         '#categories-list'
          storesList:             '#stores-list'

        ui:
          searchInput:            "input.search"
          logo:                   "strong#logo a"
          lower:                  ".lower"
          top:                    ".top"

        events:
          "click strong#logo a":  "goHome"
          "submit .top form":     "search"
          "click button.submit":  "search"
          # "keyup input.search":   "quickSearch"

        initialize: (opts) ->
          @router = opts.router

          # event triggers
          @on "sidebar:finished", @resize, @

          # override the categories display event
          @categoriesList.open = (view) ->
            this.$el.hide()
            this.$el.html(view.el)
            this.$el.slideDown(250, "easeOutExpo")

          # override the stores display event
          @storesList.open = (view) ->
            this.$el.hide()
            this.$el.html(view.el)
            this.$el.slideDown(250, "easeOutExpo")

          # override the categories remove event
          @categoriesList.remove = (view) ->
            this.$el.html(view.el)
            this.$el.slideUp(250, "easeOutExpo", -> $(this).remove())

          # override the stores display event
          @storesList.remove = (view) ->
            console.log 'stores remove'
            this.$el.slideUp(250, "easeOutExpo", -> $(this).remove())

        globalListeners: ->

          # bind app vent and other global handlers
          # app.vent.on "search:setParams", @setSearchInput

          # SearchResult.on "change:params", @setSidebar, @

          # bind to changes to search params.
          # SearchResult.listenTo @, "change:params", @setSidebar()
          SearchResult.listenTo @, "change", @setSidebar()
          # SearchResult.on "change:params", @render, @

        resize: =>
          sidebarHeight = @$el.height()
          topHeight     = @ui.top.height()
          @ui.lower.height(sidebarHeight - topHeight)

        setSidebar: (input=true) =>
          # console.dir "SidebarLayout: setSidebarContent"
          if input then @setSearchInput()

          if SearchResult.get("params")
            switch SearchResult.get("params").type
                when "categories"
                  @setCategories()
                when "text"
                  @setStores()
                  @setCategories()

        setSearchInput: ->
          if SearchResult.get("params")?
            searchTerm = SearchResult.get("query")
            @ui.searchInput.attr("value", searchTerm)
          else
            @ui.searchInput.attr("value", "")

        setStores: ->
          stores = new storesCollection()
          stores.fetch
            success: =>
              @storesView = new storesView
                collection: stores
              @storesList.show @storesView
              @storesList.$el.prev("h3").show()
              @trigger "sidebar:finished"

        setCategories: ->
          # console.log 'SidebarLayout: setCategories'
          categories = new categoriesCollection()
          categories.fetch
            success: =>
              @categoriesView = new categoriesView
                collection: categories
              @categoriesList.show @categoriesView
              @categoriesList.$el.prev("h3").show()
              @trigger "sidebar:finished"

        reset: =>
          @$el.css
            "opacity": 0
            "margin-left": "-500px"

        slideSidebarIn: =>
          @$el
          .animate
            "opacity":1
            "margin-left":0
          , 500, -> app.reqres.setHandler "sidebar:visible", -> true

        # CUSTOM EVENTS

        goHome: (e) =>
          e.preventDefault()
          # @router.navigate "/", trigger: true
          # we're going to avoid using navigate,
          # too complex to refactor at this point
          window.location = "/"

        quickSearch: =>
          # not working yet.
          value = @ui.searchInput.val()
          SearchResult.set("value", value)

        search: (e) =>
          e.preventDefault()
          value = @ui.searchInput.val()
          app.router.navigate "search/#{value}?type=text", trigger: true

        onBeforeRender: =>
          unless app.request("sidebar:visible") is true
            @reset()

        onRender: =>

          # console.dir 'SidebarLayout: render'
          setTimeout =>
            @bindUIElements()
            @globalListeners()
          , 50
          @$el.removeClass("hide")
          if app.request("sidebar:visible") is false
            @slideSidebarIn()

问题在于这一行:

searchResult.on "change:params", @setSidebarContent, @

我收到此错误:

Uncaught TypeError: Cannot call method 'show' of undefined

我认为这与未定义的区域或未通过的相关上下文有关。

所以,经过大量的研究和大约5个小时的废话后,我阅读了listenTo的文档,看来这段代码应该工作:

@listenTo searchResult, "change:params", @setSidebarContent()

然而,实际上能够让它工作的唯一方法就是完成这个确切的代码:

searchResult.listenTo @, "change:params", @setSidebarContent()

所以,我现在正在努力工作。我只是感到困惑,为什么我必须通过这种方式传递它,为什么第一种方式似乎不起作用?

1 个答案:

答案 0 :(得分:4)

()之后删除@setSidebarContent - 这也让我过去了。

@listenTo searchResult, "change:params", @setSidebarContent