2012-05-24 90 views
70

我正在实现我的第一个实际的非教程骨干应用程序,并且有关使用backbone.js的一个方面的2-ish问题没有解决对我来说很好,它涉及将视图的呈现el注入到DOM中,与使用现有元素el相关。我怀疑我会在这里为您提供一些“可教授的时刻”,并感谢您的帮助。将backbone.js视图附加到现有元素与将el插入DOM

大多数骨干查看示例我在Web中看到指定tagName,id和/或className时创建一个视图,从而创建一个从DOM不附加的el。他们通常看起来像这样:

App.MyView = Backbone.View.extend({ 
    tagName: 'li', 
    initialize: function() { 
    ... 
    }, 
    render: function() { 
     $(this.el).html(<render an html template>); 
     return this; 
    } 
}); 

但教程并不总是解释他们如何建议获取呈现EL到DOM。我已经看到了几种不同的方式。所以,我的第一个问题是:在哪里调用视图的render方法并将其el插入到DOM中? (不一定是同一个地方)。我已经看到它在路由器中完成,在视图的初始化或渲染函数中,或者仅在根级文档就绪函数中完成。 ($(function())。我可以想象任何这些工作,但有没有一个正确的方法来做到这一点?其次,我从一些HTML标记/线框开始,并将html部分转换为与骨干视图相对应的js模板。与其让视图呈现一个独立的元素并在html中提供一个锚点来坚持它,我觉得它更自然,当只有一个元素用于视图时,它不会消失,作为el本身使用现有的空的包装元素(通常是divspan)。这样,我就不必担心文件中找到的地方插入我的独立的EL,这将有可能最终看起来像这样(请注意多分层):

<div id="insert_the_el_in_here"> <!-- this is all that's in the original HTML doc --> 
    <div id="the_el"> <!-- i used to be a backbone generated, unattached el but have been rendered and inserted --> 
     <!-- we're finally getting to some useful stuff in here --> 
    </div> 
</div> 

因此,我的第二个问题的一部分对于一个基本静态的视图,从页面的HTML中直接使用现有的元素有什么不对,因为我的视图的el?这样我就知道它已经在DOM中,在正确的位置,并且调用render将立即渲染页面上的视图。我会通过将已经exixting的元素作为'el'传递给我的视图的constsructor来实现这一点。这样,在我看来,我不必担心将它粘到DOM上(使问题1成为模拟),并且调用render将立即更新DOM。例如。

<form> 
    <div someOtherStuff> 
    </div> 
    <span id="myView"> 
    </span> 
</form> 

<script type="text/template" id = "myViewContents"> . . . </script> 

<script type="application/javascript"> 
window.MyView = Backbone.View.extend({ 
    initialize: function() { 
      this.template = _.template($('#myViewContents').html()); 
      this.render(); 
    }, 
    render: function() { 
      $(this.el).html(this.template()); 
      return this; 
    } 
}); 
$(function() { 
    window.myView = new MyView({ el: $('#myView').get(0) }); 
}); 
</script> 

这是一个好方法来做它的页面静态视图?即只有其中一种观点,在任何情况下都不会消失。或者,还有更好的方法?我意识到,根据我如何使用视图,可能有不同的方式来做事情(例如,在路由器中,在父视图中,在页面加载等),但现在我正在查看初始页面加载用例。

感谢

回答

53

但绝对没有错,附加以现有的DOM节点的想法。

您甚至可以将el作为属性放在您的视图上。

window.MyView = Backbone.View.extend({ 
    el: '#myView', 
    initialize: function() { 
      this.template = _.template($('#myViewContents').html()); 
      this.render(); 
    }, 
    render: function() { 
      this.$el.html(this.template()); // this.$el is a jQuery wrapped el var 
      return this; 
    } 
}); 
$(function() { 
    window.myView = new MyView(); 
}); 

我建议是,做什么工作的...骨干的妙处在于,它是灵活的,能够满足您的需求。

就常见模式而言,通常我发现自己有一个主视图来跟踪视图,然后可能是列表视图和单个项目视图。

就初始化而言的另一种常用的模式是有某种应用程序对象的管理的东西...

var App = (function ($, Backbone, global) { 
    var init = function() { 
     global.myView = new myView(); 
    }; 

    return { 
     init: init 
    }; 
}(jQuery, Backbone, window)); 

$(function() { 
    App.init(); 
}); 

就像我之前说,虽然,没什么做事没有错误的方式,只是做什么工作。 :)

如果您需要任何帮助,请随时在twitter @ jcreamer898上打我,也可以查看@derickbailey,他是一位BB大师。

玩得开心!

+1

另外,感谢您使用模块模式的提示。我一直在用require.js作为实现模块和动态加载以及所有好东西的一种方式,但是我们使用了很多非AMD插件和现有的代码,我觉得它可能更简单,并且更容易忽略有意义的文件和模块中的东西,在可能的情况下使用类似上面指出的模块模式的东西,并将它们连接/缩小以用于生产。 –

+1

绝对的,require.js是一个很好的解决方案,但它肯定会很棘手。通常我只会使用像模块模式这样的模式,然后使用命名空间将事情保持在窗口外。很高兴我能帮上忙! – jcreamer898

+0

感谢您指向正确的方向。还发现$(this.el)的工作方式与此不同。$ el –

18

您也可以将HTML DOM元素对象作为选项的'el'属性发送到视图中。

window.MyView = Backbone.View.extend({ 
    initialize: function() { 
      this.template = _.template($('#myViewContents').html()); 
      this.render(); 
    }, 
    render: function() { 
      this.$el.html(this.template()); // this.$el is a jQuery wrapped el var 
      return this; 
    } 
}); 
$(function() { 
    window.myView = new MyView({ 
     el: document.getElementById('myView') 
    }); 
}); 
+4

准确的答案我正在寻找。谢谢! – zachwill