在父视图上失去委派的骨干视图事件重新呈现

时间:2014-09-17 14:41:17

标签: javascript jquery backbone.js coffeescript

我已经看到这个问题出现了几次但是我自己无法解决它 - 或者我不太明白答案。很多事情都在谈论使用.empty().append()而不是.html()以及确保始终引用视图的$el值而不是直接访问DOM的内容。仍然没有骰子。

如果你看看这个jsbin,你会发现更改选择框值会在第一次重新渲染包装器视图,但是后续更改什么都不做 - 它会丢失它的事件。

http://jsbin.com/fuvoba/7/edit(向任何咖啡师仇敌道歉)

知道为什么会这样吗?

非常感谢和互联网品脱,一如既往:)

编辑 - 以为我也将内联代码包含在内:

class ArchivesDropdownView extends Backbone.View
  template: '<select><option>One</option><option>Two</option></select>'
  initialize: () ->
    console.log 'Initialised the select dropdown'
  render: () ->
    this.$el.find('#dropdown').empty().append @template
    console.log 'Rendered the select dropdown'
    return this
  events:
    'change select': 'updateSelect'
  updateSelect: () ->
    console.log 'Updated select dropdown.'
    wrapperView.render()


class WrapperView extends Backbone.View
  template: 'Please select: <div id="dropdown"></div><div id="random"><%=randomNum%></div>'
  render: () ->
    console.log 'Rendered the wrapper'

    this.$el.empty().append _.template(@template)(randomNum: Math.random())

    if !this.archivesDropdownView
      this.archivesDropdownView = (new ArchivesDropdownView().render())

    this.archivesDropdownView.render()

    return this


wrapperView = new WrapperView()
$('body').empty().append wrapperView.render().$el

2 个答案:

答案 0 :(得分:3)

在将视图this.archivesDropdownView.delegateEvents()添加到其他视图后添加$el

  this.$el.find('#dropdown').empty().append this.archivesDropdownView.$el
  this.archivesDropdownView.delegateEvents()

但我不喜欢你的架构,你应该使用子视图的全局引用来渲染父视图。改为使用事件,例如在父视图和子视图之间共享模型,并从子视图触发事件以重新呈现父视图。

以下是一个工作示例http://jsbin.com/dehujecejape/1/edit

答案 1 :(得分:1)

你有这样的问题,因为你不按照应该做的方式做事。当其中一个组件发生变化时,为什么要重新渲染整个容器?当然,这种方法会带来各种各样的麻烦。

我建议您创建第三个组件,并在选择框更改时更新它:

class ArchivesDropdownView extends Backbone.View      
  template: '<select><option>One</option><option>Two</option></select>'
  initialize: (opts)->
    console.log 'Initialised the select dropdown'    
    @listener = opts.listener
  render: ->
    console.log 'Rendered the select dropdown'
    @$el.html @template    
  events:
    'change': 'updateSelect'
  updateSelect: ->
    @listener.render()

class RandomGeneratorView extends Backbone.View
  template: '<%=randomNum%>'
  render: ->
    @$el.html _.template(@template)(randomNum: Math.random())    

class WrapperView extends Backbone.View
  template: 'Please select: <div id="dropdown"></div><div id="random"></div>'
  initialize: ->
    console.log "wrapper init"
    randomElement = new RandomGeneratorView()
    @randomGeneratorView = randomElement.render()
    @archivesDropdownView = (new ArchivesDropdownView(listener: randomElement)).render()

  render: ->
    @$el.html @template  
    @randomContainer = @$el.find "#random"
    @dropdownContainer = @$el.find "#dropdown"
    @dropdownContainer.html @archivesDropdownView
    @randomContainer.html @randomGeneratorView
    @$el

$('body').html (new WrapperView()).render()

这里是modified JSBin