【问题标题】:Backbone events not delegated to new element after setElement在 setElement 之后没有委托给新元素的主干事件
【发布时间】:2017-07-06 13:04:51
【问题描述】:

我正在使用 Underscore 模板实现 Backbone 视图。使用 setElement 函数将视图 el 替换为模板 html。该函数的声明说“......将视图的委托事件从旧元素移动到新元素”但由于某种原因这不起作用。任何想法为什么这不能像 Backbone 声明中描述的那样工作?

这是一个例子(视图的相关部分):

     initialize: function(args) {
        _.extend(this, args);
        this.listenTo(this.model, 'change', this.render);
     },

     events: {
        'click .active-area': '_test'
     },

     _test: function() {
        // After "setElement" this doesn't fire anymore.
        this.model.set('color', 'green');
     },

     render: function() {
        // After this the "click" listener no longer exists.
        this.setElement(this.template(this.model.toJSON());

        return this;
     }

【问题讨论】:

    标签: javascript backbone.js underscore.js


    【解决方案1】:

    this.template(...) 不是 DOM 中的元素。

    在您的代码中,setElement 从旧元素中移除事件监听器,然后将它们委托给新元素,新元素只存在于内存中,而不是页面上。

    您应该简单地更改当前元素的内容。

    this.$el.html(this.template(this.model.toJSON()));
    

    我需要用模板 html 替换整个元素 html,这就是为什么我需要使用 setElement 函数。

    假设您有以下 HTML:

    <div id="currentView"><!-- view's root (el) -->
        <button type="button" class="active-area">Click me</button>
        <span class="color"><%= color %></span>
    </div>
    

    添加一个包装 div 并将 #currentView div 移动到模板中。

    <div class="wrapper"><!-- view's root (el) -->
        <div id="currentView">
            <button type="button" class="active-area">Click me</button>
            <span class="color"><%= color %></span>
        </div>
    </div>
    

    现在this.$el.html 将交换整个元素。


    如果你真的希望视图交换它自己的根元素,你可以创建一个新元素,然后使用 jQuery 的replaceWith 将新元素放置在旧元素的位置。

    render: function() {
        // create a new element from the template
        var $newEl = $(this.template(this.model.toJSON()));
    
        // completely replace the current element in the DOM
        this.$el.replaceWith($newEl);
    
        // then tell the view
        this.setElement($newEl);
    
        return this;
    }
    

    【讨论】:

    • 好点!实际上,此解决方案不适用于我的情况。我需要用模板 html 替换整个元素 html,这就是我需要使用 setElement 函数的原因。
    • @QD 在您的页面中创建一个包装元素,并将该元素根移动到模板中。
    • 对不起,我没有完全关注。你能给我更多解释一下这是如何工作的吗?
    • 是的,你是对的,我的问题,尤其是 cmets 并不是最清楚的。在我的情况下,如果我将包装器与模板完全分开,您的解决方案似乎有效。这样它只能作为视图的基本元素。如果我将它放在模板中,它会被覆盖,并且只呈现最后一个元素。
    • 没有包装就可以正常工作。 Backbone 视图生成一个 div 作为默认 el,解决方案只是替换它。 setElement-function 仅将事件侦听器重新委托给新的 dom 元素。感谢 Emile Bergeron 的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    相关资源
    最近更新 更多