Click事件处理程序仅在Backbone.js中工作一次

时间:2014-02-04 14:42:41

标签: javascript jquery backbone.js javascript-events backbone-events

我是Backbone的新手,并且正在使用Rails中的jQuery。在我的视图的render方法中,我使用delegateEvents将事件处理程序绑定到ID为btn-go的按钮的“click”事件。此按钮本身由相关视图呈现。

单击该按钮可将表单的值存储在数组中,并使视图重新呈现。此按钮本身由相关视图呈现。这是第一次单击按钮时的工作,但第二次没有任何反应,即使视图正确地重新渲染其模板。

class MyApp.Views.ChainsNew extends Backbone.View

    # @template is defined by a conditional inside render()

    render: (step_number) ->
        window.model = @model
        @step_number = step_number

        @template = if @step_number is 1 then JST['chains/new'] else JST['chains/step']
        $(@el).html(@template())

        @delegateEvents({
            'click #btn-go': 'add_step'
        })
        @

    add_step: ->
        #divide array into arrays of steps before and after step being edited
        steps = @model.get('steps')
        array1 = steps.slice(0, @step_number - 1)
        array2 = steps.slice(@step_number)
        array1.push(@$el.find('textarea').val())
        newArray = array2.concat(array1)

        @model.set({
            steps: newArray
        })

路由器调用视图的render方法。正如您在下面的代码中看到的那样,路由器正在侦听模型上的change事件。这会导致它更新URL,从而触发路由器的step方法被调用,并且在该方法中最终调用视图的render方法。

class MyApp.Routers.Chains extends Backbone.Router
    routes:
        'chains/new(/)': 'new'
        'chains/new/step/:step_number(/)': 'step'

    initialize: ->
        # Model
        @model = new MyApp.Models.Chain()
        @listenTo(@model, "change", ->
            @goto_step_number @model.get('steps').length + 1
        )

        # Views
        @view_new = new MyApp.Views.ChainsNew({
            model: @model
        })


    step: (url_step_number) ->
        # Before rendering the view, make sure URL & number of steps in model are correctly related
        url_step_number = parseInt url_step_number
        steps_entered = @model.get('steps').length

        if url_step_number > steps_entered + 1
            @goto_step_number steps_entered + 1
        else
            $('#main-container').html(@view_new.render(url_step_number).el)

    new: ->
        @goto_step_number 1

    goto_step_number: (step_number) ->
        @.navigate('chains/new/step/' + step_number, trigger: true)

为什么第二次单击按钮时没有发生任何事情?我猜测事件处理程序没有正确绑定到按钮,但我不明白为什么。

1 个答案:

答案 0 :(得分:1)

你的问题就在这里:

$('#main-container').html(@view_new.render(url_step_number).el)

来自fine manual

  

.html(htmlString)
  [...]
  当.html()用于设置元素的内容时,该元素中的任何内容都将被新内容完全替换。此外,在使用新内容替换这些元素之前,jQuery会从子元素中删除其他构造(如数据和事件处理程序)。

请注意删除其他构造,例如数据和事件处理程序部分。事件的顺序如下:

  1. 您致电render
  2. render调用delegateEvents将jQuery事件委托人附加到视图的el
  3. 您致电$x.html(view.el)view.el已经存在,所以jQuery会分离所有事件绑定(包括您刚刚在 2 中添加的那个),清除{{1}然后将$x放回view.el
  4. 但是当$x被放回页面时,事件已经消失。这大致相当于你正在做的事情:

    view.el

    # In the view...
    add_step: ->
        re_render(@step_number + 1)
    

    演示:http://jsfiddle.net/ambiguous/4rJyB/

    您需要一直停止致电v = new YourView $('#main-container').append(v.render(1).el) re_render = (step_number) -> $('#main-container').html(v.render(step_number).el) 。一旦视图在页面上,您可以简单地告诉它重新渲染自己,这就是您需要做的所有事情。因此,如果视图已呈现一次以将其.html转换为el,则只需:

    #main-container

    就是这样。然后,您可以从@view_new.render(url_step_number) 中删除@delegateEvents来电并使用视图中的常用事件地图:

    render