繁体   English   中英

如何将 Backbone.View 绑定到 DOM 中类似元素列表中的“单个”DOM 元素

[英]How to bind a Backbone.View to a 'single' DOM element in a list of similar elements in the DOM

我有以下页面结构:

<ul class="listOfPosts">
   <li class="post WCPost" data-postId="1">
      <div class="checkbox"><input type="checkbox" class="wcCheckbox"/></div>
      <div class="PostContainer>
       <!-- some other layout/content here -->
       <ul class="listOfLabels">
          <li class="label"> Label 1</li>
          <li class="label"> Label 2</li>
       </ul>
      </div>
   </li>
   <li class="post WCPost" data-postId="2">...</li>       
   <li class="post WCPost" data-postId="3">...</li>
   <li class="post WCPost" data-postId="4">...</li>
   ...
</ul>

这是过于简单的视图:

  var MyView = Backbone.View.extend({
    el:$('.listOfPosts'),

    initialize: function() {
         _.bindAll(this,"postClicked");
    },

    events: {
        "click .wcCheckbox":"postClicked"
    },

    postClicked: function() {
         alert("Got a a click in the backbone!");
        }
  });

问题:我想知道被点击的帖子的数据ID。 使用简单的 JQuery 我可以执行以下操作:

$('.wcCheckbox').live('click' function() {
    alert("Data id of post = "+$(this).parents('.WCPost').data('data-postId'));
}

现在我知道 Backbone 会进行事件委托,因此它需要 el 属性中的 DOM 引用。 如果我给它.listOfPosts,那么事件似乎会完美触发,但要检查“哪些”帖子,我必须继续遍历 DOM 并挑选出被选中的元素?? 在我看来,这将是相当昂贵的。 我如何在 Backbone 中为每个单独的帖子执行此操作,。 即?,如何将视图绑定到每个单独的 li.WCPost?

注意:我没有使用普通的香草 jQuery,因为我需要编写的代码最好使用 Backbone 的模块化设计完成,但由于我不是 Backbone 的专业人士(还;)有点困惑......

据我所知,在你的postClicked() function 中使用类似$(event.target).data('postId')的东西是做这种事情的正常方法。

事件的广泛使用起初可能看起来不寻常,但如果使用得当,这是改进代码组织的好方法。 在大多数情况下,您确实可以从事件中获得所需的所有数据,特别是如果您有 jQuery。 (Note that the event passed to your postClicked function is a regular jQuery event object, and everything you can find about it could be applied. Backbone.js uses jQuery's delegate() function to bind events.)

* * *

但是,您仍然可以在视图的initialize()方法中自己绑定事件。

 initialize: function() { // Custom binding code: this.$('.wcCheckbox').live('click' function() { alert("Data id of post = "+$(this).parents('.WCPost').data('data-postId')); } // No need for this anymore: // _.bindAll(this,"postClicked"); },

this.$(<selector>)是一个 function ,它自动将 jQuery 选择器范围限定为您的视图,相当于$(<selector>, this.el) 。)

* * *

另一种解决方案(也许最终是最自然的,但首先需要一些工作)是创建一个PostView class,并将其用于单个帖子和绑定复选框单击事件。

要显示帖子,请在您的帖子列表视图中通过Posts集合查看 go,为每个Post实例创建一个视图,并将 append 它添加到.listOfPosts元素。

您不再需要解决访问帖子 ID 的问题,因为您将在PostView上绑定复选框单击事件。 So, in the handler function would be able to find post's ID easily—either through related model ( this.model.get('id') ) or through view's element ( $(this.el).data('postId') ) .

* * *更新

现在我独立于 Backbone 生成了我的帖子的 DOM,我如何像我在问题中提到的那样“改造”每个帖子的视图?

我不想仅仅为了适应 Backbone 就重构大量的客户端代码。 但是如何将视图绑定到每个 li?

如果您决定使用 MVC 和面向对象的 JavaScript 来 go,那么您不应该直接为您的帖子管理 DOM 元素:您创建PostView实例,然后它们反过来创建相应的元素,例如在 todos.js 中,并用呈现的模板。 (如果您不想自动创建元素,Backbone 允许您通过在子类化时指定el属性手动将新创建的视图绑定到元素。这样,您可以将视图绑定到现有元素,例如,在初始页面加载。)任何与特定帖子相关的 DOM 修改都应在PostView class 内进行。

OOP 方法相对于基于 DOM 的一些优势:

  • 视图比 DOM 元素更适合数据存储。

    请注意,在您当前的方法中,您正在广泛使用data属性——例如,存储帖子的 ID。 但是,如果您正在操作视图,则不需要这样做:每个PostView已经知道其相关的 model,因此您可以通过例如view.model.get('postId')轻松获取帖子 ID,如以及您想要的任何其他发布数据。

    您还可以存储不属于 Post model的特定于视图的数据:例如,animation 和/或显示 state(扩展、选中、...)。

  • 视图更适合定义元素的行为。

    例如,如果您想为每个帖子指定一个复选框单击事件处理程序,则将此代码放入您的PostView class 中。 这样,事件处理程序就知道所有发布数据,因为视图可以访问它。 此外,代码结构更好——处理特定帖子,属于PostView ,不会妨碍您。

    另一个例子是在视图上定义一个render() function 的约定。 模板 function 或模板字符串存储在视图属性template中, render()渲染该模板并使用生成的 HTML 填充视图元素:

     render: function() { $(this.el).html(this.template({ modelData: this.model.toJSON() })); },
  • 操作 DOM 可能比操作对象慢。

但是,基于 DOM 的方法(您现在似乎一直在使用)有其优点,尤其是对于不太复杂的应用程序。 另请参阅: Object 面向 Javascript 与纯 jQuery 和.data 存储

有没有办法将视图绑定到不是由主干生成的当前和未来的 DOM 元素?

这是否意味着骨干需要从一开始就使用并且很难“改造”?

如上所示,您不需要将视图绑定到未来的DOM 元素(使用视图来操作它们)。

关于在页面初始化时绑定到页面上已经存在的 DOM 元素,我不知道这样做的“正确”方法。 我目前的方法是清除现有元素并从头开始创建视图,这将自动创建相应的 DOM 元素。

这意味着浏览器在页面初始化时需要做一些额外的工作。 对我来说,OOP 的优势证明了这一点。 从用户的角度来看,我想这也很好:在初始初始化之后,一切都会更快,因为在用户执行诸如注销之类的操作之前不需要重新加载页面。

(顺便说一句,我想我应该澄清使用 MVC 方法的要点,至少对我来说:创建一个客户端应用程序,基本上,它自己完成了大部分工作,使用后端服务器提供的 API。服务器在 JSON 中为模型提供数据,并且您的客户端应用程序执行 rest,广泛使用 AJAX。如果您在用户与您的站点交互时执行正常的页面加载和繁重的 MVC 客户端可能是开销。是您将不得不重构一些代码,根据您的要求和资源,这可能不是一个选项。)

请注意,事件传递对自身及其起源点的引用,在我看来,这是访问事件起源的最简单方法。

像这样尝试,看看这是否是您需要的(并且不那么复杂):

var MyView = Backbone.View.extend({

    el:$('.listOfPosts'),

    initialize: function() {
         _.bindAll(this,"postClicked");
    },

    events: {
        "click .wcCheckbox":"postClicked"
    },

    postClicked: function(e) {
        alert("Here is my event origin: "+e.target);
    }

});

可以从事件中获得大量数据,如下所示: http://www.quirksmode.org/js/events_properties.html

一旦您对 javascript 事件有所了解,您可能会研究 PubSub/Observer 模式以获得更多解耦的 UI 组件,这里有一个很好的介绍:

http://blog.bobcravens.com/2011/01/loosely-coupled-javascript-using-pubsub/

没有什么能阻止您嵌套视图。 即,外视图代表UL。 UL 视图将呈现一堆内部 LI 视图。 您可以尽可能深入地嵌套视图。

我一直以这种方式做事非常成功。

暂无
暂无

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

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