marionetteItemView 子视图,未触发事件

marionetteItemView Childview, events not triggered

所以这是 ParentView 上的代码: 相关方法:

openChildView: function(){

    var childView = new ChildView({
            container: $container //container where the child map should be appended
    });

    childView.show();
}

这是 ChildView 的代码:

    ChildView = Marionette.ItemView.extend({

        template: _.template($(templates_c).filter('#my_child_view_template').html()),

        ui: {
            saveButton: 'button.js-save',
            uploadButton: 'button.js-upload',
            deleteButton: 'button.js-discard'
        },
        events: {
            'click @ui.saveButton': function() {
                log.debug('save');
            },
            'click @ui.uploadButton': function() {
                log.debug('upload');
            },
            'click @ui.deleteButton': function() {
                log.debug('delete');
            }
        },
        show: function() {
            this.render();
        },

        initialize: function(){
            this.container = this.options.container;
            this.id = this.options.id;
        },

        remove: function(){
            // Don't know yet if this is the proper way, but for now it works
            this.container.find('.container-child-view').remove();
        },

        render: function(){
            this.container.append(this.template({
                id: this.id,
                img: '...'
            }));

            log.debug('on render');
            this.bindUIElements();
            this.delegateEvents();

            return this;
        }
    });

这是 ChildView 模板的代码:

<script type="text/x-template" id="my_child_view_template">
    <div class="block container-child-view">
        <div class="block-title">
            <h4><%= id %></h4>
        </div>

        <div class="img">
            <img src="<%= imgUrl %>">
        </div>
        <div class="row text-center">
            <div class="btn-group btn-group-xs">
                <button id="discard" type="button" class="js-discard btn btn-alt btn-warning"><i class="fa fa-times-circle"></i> Cancel</button>
                <button id="upload" type="button" class="js-upload btn btn-alt btn-primary"><i class="fa fa-upload"></i> Upload</button>
                <button id="save" type="button" class="js-save btn btn-alt btn-primary"><i class="fa fa-save"></i> Save</button>
            </div>
        </div>
    </div>
</script>

子视图呈现在父视图之上,但没有触发任何事件(保存、丢弃、上传)。

任何hints/ideas?

谢谢。

.delegateEvents() 绑定事件的方式是委托给视图的 el。在 source 你会看到这个:

delegate: function(eventName, selector, listener) {
  this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
},

如您所见,在视图的 $el 上调用了 jQuery .on()。如果将 selector 参数传递给 .delegate()(例如 .js-save),则选择器的事件将委托给其包含视图的 el.

您覆盖 .render() 的方式是您选择用“全能”this.el 代替 this.container。调用 this.delegateElements() 仍然会调用 .delegate() 来绑定 this.el,而您的视图 实际上 位于 this.container 中。视图事件冒泡到未绑定的容器。

快速修复可能是像这样覆盖渲染:

    render: function(){
        this.container.append(this.template({
            id: this.id,
            img: '...'
        }));

        log.debug('on render');
        this.bindUIElements();

        // .setElement is an internal method that will
        // make your container the view's el and will call
        // .delegateEvents on this new el
        this.setElement();

        return this;
    }
});

我可能不能称自己为正直的 Marionette 社区居民,除非我还为您提供了更面向框架的解决方案。在我看来,您已经覆盖了 .render,因为您想要 1.ItemView 渲染到特定的包含元素和 2。 您想将非模型数据加载到模板中。

1。设置视图 el

Backbone 将采用现有的 DOM 元素作为视图的 el。只需在视图实例化时传入选择器或 jQuery 对象,

var childView = new ChildView({ el: $container });

Marionette .render() 方法会将视图附加到 $container

2。将非模型数据传递给您的模板

Marionette 有这个方便的视图实用程序,templateHelpers,它允许您将数据放入模板渲染器的范围内。数据可以是任何 JS 对象,包括函数。只需在您的视图中包含 属性。

templateHelpers: function () {
    return {
      img: function(){
        return 'http://some-domain.com/img/" + this.id;
      },

      id: this.id
    };
  }
});

其中,在此版本中 templateHelper this 是视图的上下文。