【问题标题】:Click event handler only working once in Backbone.js单击事件处理程序仅在 Backbone.js 中工作一次
【发布时间】:2014-02-04 14:42:41
【问题描述】:

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

单击按钮将表单的值存储在一个数组中,并导致视图重新呈现。此按钮本身由相关视图呈现。这在我第一次单击按钮时有效,但第二次没有任何反应,即使视图确实正确地重新渲染了它的模板。

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)

为什么我第二次单击该按钮时没有任何反应?我猜测事件处理程序没有正确绑定到按钮,但我不知道为什么。

【问题讨论】:

  • 你的两个模板都有“*btn-go”按钮吗?尤其是“链/步”?
  • @DavidSulc 是的。
  • delegateEvents 调用 (jsfiddle.net/ambiguous/2SnDn) 或仅与普通的 events 映射 (jsfiddle.net/ambiguous/8q8XH) 一起工作正常。你是如何使用这个视图的?什么触发了render 调用?
  • @muistooshort 我更新了我的帖子以显示我的路由器的代码,以及单击 go 按钮导致的方法调用序列的说明。

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


【解决方案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 中添加的绑定),清除$x,然后放入@ 987654332@回$x

但是当view.el 被放回页面时,事件已经消失了。这大致相当于你正在做的事情:

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

v = new YourView
$('#main-container').append(v.render(1).el)
re_render = (step_number) ->
    $('#main-container').html(v.render(step_number).el)

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

你需要停止呼叫.html。一旦视图出现在页面上,您可以简单地告诉它重新呈现自己,这就是您需要做的一切。因此,如果视图已经渲染一次以将其el 转换为#main-container,您只需要:

@view_new.render(url_step_number)

就是这样。然后您可以从render 中删除@delegateEvents 调用,并在视图上使用通常的事件映射:

class MyApp.Views.ChainsNew extends Backbone.View
    events:
        'click #btn-go': 'add_step'
    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())
        @
    #...

【讨论】:

  • 完美,谢谢!我非常专注于查看特定于 Backbone 的内容,以至于忽略了简单的 jQuery 问题。但是有一个问题——为什么即使是第一次点击按钮也能正常工作?似乎我对 delegateEvents 的调用应该永远不会起作用,因为即使是第一次视图还没有被插入到 DOM 中。
  • 我认为第一个 .html 调用有效,因为 view.el 不在 #main-container 中,所以步骤 3 的第一部分(“jQuery 分离所有事件绑定") 不会发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
相关资源
最近更新 更多