Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将主干视图重新分配给新创建的DOM元素_Javascript_Backbone.js - Fatal编程技术网

Javascript 将主干视图重新分配给新创建的DOM元素

Javascript 将主干视图重新分配给新创建的DOM元素,javascript,backbone.js,Javascript,Backbone.js,我正在创建一个搜索结果页面,将主干网与咖啡脚本和把手结合使用。我有两个视图:一个用于结果列表(ListView),第二个视图用于单个结果(ResultView)。简化代码: ListView = Backbone.View.extend el: $("ul#results") ... addItem: (result) -> resultView = new ResultView({ model: result }) resultView.

我正在创建一个搜索结果页面,将主干网与咖啡脚本和把手结合使用。我有两个视图:一个用于结果列表(ListView),第二个视图用于单个结果(ResultView)。简化代码:

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:
    ...
简要说明:

  • 列表视图分配给
    ul#结果
  • 将结果添加到listview时,将创建一个ResultView,该视图了解其父视图并呈现自身
  • 对于结果视图,将创建元素
    li.result
    (默认主干行为)
这是我用来呈现搜索结果的(简化)模板:

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

  • 这是我的难题,您可能已经发现了:我在我的主干ResultView和模板中定义了一个
    li.result
    。我不能做的是:

    • 将ResultView绑定到我的模板中的
      li.result
      ,因为它在DOM中还不存在
    • 从我的模板中删除
      li.result
      ,因为我仍然需要它来为那些没有启用JavaScript的人呈现页面服务器端
    有没有一种方法可以(优雅地)在元素实例化后将主干视图重新分配给元素?或者简单地说,我是否可以将ResultView引用到临时元素,呈现模板,然后将其移动到
    ul#result
    ?还是我看错了


    谢谢

    我发现,当您尝试支持服务器端渲染视图和客户端视图时,事情总是会变得更加复杂。您在这里描述的场景就是一个完美的例子

    如果可能的话,我会将页面的呈现移到客户端,这将大大有助于简化代码

    也就是说,如果您确实希望保留服务器呈现的视图,我可能会在页面加载后对集合执行fetch(),以从服务器获取所有对象。然后可以调整ResultView initialize函数以执行以下检查

    ResultView = Backbone.View.extend
      initialize: (attributes) ->
        exisitingElement = $('result_' + attributes['id'])
        if exisitingElement?
          @el = exisitingElement 
          @delegateEvents()
    
    然后您将更改模板以包含唯一id

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


  • 这样,ResultView将在向页面呈现新元素之前查找现有元素。重新分配@el属性后手动调用delegateEvents(),可确保您定义的任何事件仍能工作。

    我建议您只需从视图中触发渲染事件,然后在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');
    }
    

    谢谢你的回复,但我认为这并不能解决我的问题;元素是在渲染后创建的,因此“existingElement”永远不会发生。但也许我想要的东西做不到(有点像第二十二条军规),所以我还是要看看你的建议。谢谢你!我实际上把你的答案和斯科特·哈维的答案结合起来了;我使用了render触发器,重新分配了新的
    li.result
    ,然后使用@delegateEvents确保事件被绑定。