【问题标题】:Marionette.js - can I detect onAppend?Marionette.js - 我可以检测到 onAppend 吗?
【发布时间】:2013-10-09 09:27:43
【问题描述】:

我有一个愚蠢的问题,我唯一的解决方案是一个草率的 hack,现在给我带来了其他问题。

See my fiddle,

或在此处阅读代码:

HTML:

<input id='1' value='input1' />
<template id='template1'>
    <input id='2' value='input2' />
</template>

JS - 项目视图声明:

// Declare an ItemView, a simple input template.
var Input2 = Marionette.ItemView.extend({

    template: '#template1',
    onRender: function () {
        console.log('hi');
    },

    ui: { input2: '#2' },

    onRender: function () {

        var self = this;

        // Despite not being in the DOM yet, you can reference
        // the input, through the 'this' command, as the
        // input is a logical child of the ItemView.
        this.ui.input2.val('this works');

        // However, you can not call focus(), as it 
        // must be part of the DOM.
        this.ui.input2.focus();

        // So, I have had to resort to this hack, which 
        // TOTALLY SUCKS.

        setTimeout(function(){
          self.ui.input2.focus();
          self.ui.input2.val('Now it focused. Dammit');  
        }, 1000)
    },

})

JS - 控制器

// To start, we focus input 1. This works.
$('#1').focus();

// Now, we make input 2.
var input2 = new Input2();

// Now we 1. render, (2. onRender is called), 3. append it to the DOM.
$(document.body).append(input2.render().el);

正如上面所见,我的问题是我无法在渲染后(onRender)将 View 调用聚焦于自身,因为它尚未附加到 DOM。据我所知,没有其他名为 onAppend 的事件可以让我检测到它何时实际附加到 DOM。

我不想从 ItemView 之外调用焦点。为了我的目的,它必须从内部完成。

有什么好主意吗?

更新

事实证明 onShow() 在 Marionette.js 中的所有 DOM 追加上都被调用,无论是 CollectionView、CompositeView 还是 Region,它不在文档中!

谢谢一百万,lukaszfiszer。

【问题讨论】:

    标签: javascript backbone.js marionette


    【解决方案1】:

    解决方案是将ItemView 呈现在Marionette.Region 中。这样,一旦将视图插入 DOM,就会在视图上调用 onShow 方法。

    例子:

    HTML

    <input id='1' value='input1' />
    <div id="inputRegion"></div>
    <template id='template1'>
      <input id='2' value='input2' />
    </template>
    

    JS 项目视图

    (...)
    
    onShow: function () {
        this.ui.input2.val('this works');
        this.ui.input2.focus();
    },
    
    (...)
    

    JS 控制器

    $('#1').focus();
    
    var inputRegion = new Backbone.Marionette.Region({
      el: "#inputRegion"
    });
    
    var input2 = new Input2();
    
    inputRegion.show(input2);
    

    Marionette 文档中的更多信息:https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.region.md#region-events-and-callbacks

    【讨论】:

    • 谢谢 - 看到这正是我正在寻找的东西。可惜它只适用于区域,我只是认为这是 Marionette.js 中的一个草率设计。看看我对我刚刚解决的问题的回答 - 你认为这是个好主意吗?
    • 你是个坏蛋。这完全回答了我的问题!非常感谢。
    【解决方案2】:

    好吧,我设法通过扩展 Marionette.js 解决了这个问题,但如果其他人有更好的不涉及扩展库的想法,我会很高兴接受它并给你买一个甜甜圈.

    // After studying Marionette.js' annotated source code,
    // I found these three functions are the only places
    // where a view is appended after rendering. Extending
    // these by adding an onAppend call to the end of
    // each lets me focus and do other DOM manipulation in
    // the ItemView or Region, once I am certain it is in
    // the DOM.
    
    _.extend(Marionette.CollectionView.prototype, {
      appendHtml: function(collectionView, itemView, index){
        collectionView.$el.append(itemView.el);
        if (itemView.onAppend) { itemView.onAppend() }
      },
    });
    
    _.extend(Marionette.CompositeView.prototype, {
      appendHtml: function(cv, iv, index){
        var $container = this.getItemViewContainer(cv);
        $container.append(iv.el);
        if (itemView.onAppend) { itemView.onAppend() }
      },  
    });
    
    _.extend(Marionette.Region.prototype, {
     open: function(view){
        this.$el.empty().append(view.el);
        if (view.onAppend) { view.onAppend() }
      },  
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      相关资源
      最近更新 更多