简体   繁体   English

将Backbone View重新分配给新创建的DOM元素

[英]Reassign Backbone View to newly created DOM element

I'm creating a search results page using Backbone in combination with CoffeeScript and Handlebars. 我正在使用Backbone与CoffeeScript和Handlebars一起创建搜索结果页面。 I have two views: one for the list of results (ListView) and the second view is for a single result (ResultView). 我有两个视图:一个用于结果列表(ListView),第二个视图用于单个结果(ResultView)。 Simplified code: 简化代码:

ListView = Backbone.View.extend
  el: $("ul#results")
  ...

  addItem: (result) ->
    resultView = new ResultView({
      model: result
    })
    resultView.parentView = this
    this.el.append(resultView.render().el)

ResultView = Backbone.View.extend
  tagName: "li"
  className: "result"
  events:
    ...

Short explanation: 简短说明:

  • The ListView is assigned to ul#results ListView被分配给ul#results
  • When a result is added to the listview, a ResultView is created, that has knowledge of its parent and renders itself 将结果添加到列表视图时,会创建一个ResultView,它知道其父级并呈现自身
  • For the ResultView an element li.result is created (default Backbone behaviour) 对于li.result ,创建了一个元素li.result (默认的Backbone行为)

This is (simplified) the template I'm using to render a search result: 这是(简化)我用来呈现搜索结果的模板:

<li class="result">
   <h1>
     <a href="{{link}}">{{title}}</a>
   </h1>
   <p>{{snippet}}</p>
</li>

Here's my conundrum, as you may have discovered yourself: I define a li.result in my Backbone ResultView, and in my template. 这是我的难题,你可能已经发现了自己:我在Backbone ResultView 我的模板中定义了一个li.result What I can't do: 做不到的事:

  • Bind the ResultView to the li.result in my template because it doesn't exist yet in the DOM 将ResultView绑定到模板中的li.result ,因为它在DOM中尚不存在
  • Remove the li.result from my template, because I still need it to render the page server side for those who don't have JavaScript enabled 从我的模板中删除li.result ,因为我仍然需要它为那些没有启用JavaScript的人呈现页面服务器端

Is there a way to (elegantly) re-assign a Backbone view to an element after its been instantiated? 有没有办法(优雅地)在实例化后将一个Backbone视图重新分配给一个元素? Or put simply, can I reference ResultView to a temporary element, render the template and then move it into ul#result ? 或者简单地说,我可以将ResultView引用到临时元素,渲染模板然后将其移动到ul#result吗? Or am I looking at it the wrong way? 或者我是以错误的方式看待它?

Thanks! 谢谢!

I would suggest to simply trigger a rendered event from your view and then perform your operations in an onRendered callback like so: 我建议只从视图中触发渲染事件,然后在onRendered回调中执行操作,如下所示:

initialize: function() {
  this.bind('rendered', onRendered);
},

onRendered: function() {
   // do onRendered stuff
   // eg. remove an element from the template
},

render: function() {
  // your render stuff
  this.trigger('rendered');
}

I've found that things are always going to get a bit more complicated when you try to support server side rendered views and client side views. 我发现当你试图支持服务器端渲染视图和客户端视图时,事情总会变得复杂一些。 The scenario you are describing here is a perfect example of that. 您在这里描述的场景就是一个很好的例子。

If at all possible I would move the rendering of the page to the client side which will greatly help to simplify your code. 如果可能的话,我会将页面的呈现移动到客户端,这将极大地帮助简化代码。

That being said if you did want to keep the server rendered views I would probably perform a fetch() on your collection after the page has loaded to get all the objects from the server. 话虽这么说,如果你确实想要保持服务器呈现的视图,我可能会在页面加载后从你的集合上执行fetch()以从服务器获取所有对象。 You could then adjust your ResultView initialize function to do the following check. 然后,您可以调整ResultView初始化函数以执行以下检查。

ResultView = Backbone.View.extend
  initialize: (attributes) ->
    exisitingElement = $('result_' + attributes['id'])
    if exisitingElement?
      @el = exisitingElement 
      @delegateEvents()

Then you would change your template to include a unique id. 然后,您将更改模板以包含唯一ID。

    <li id="result_{{id}}" class="result">
       <h1>
         <a href="{{link}}">{{title}}</a>
       </h1>
       <p>{{snippet}}</p>
    </li>

This way the ResultView will look for an existing element before rendering a new one to the page. 这样,ResultView将在向页面呈现新元素之前查找现有元素。 Manually calling delegateEvents() after reassigning the the @el property ensures that any events you have defined will still work. 在重新分配@el属性后手动调用delegateEvents()可确保您定义的任何事件仍然有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM