草庐IT

javascript - 如何将Backbone.View绑定(bind)到DOM中类似元素列表中的 'single' DOM元素

coder 2025-03-19 原文

我具有以下页面结构:

<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>

这是过于简单的 View :
  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进行事件委托(delegate),因此它需要el属性中的DOM引用。如果我给它.listOfPosts,那么该事件似乎可以完美触发,但是要检查“哪些”帖子,我将不得不继续遍历DOM并挑选出选定的元素!!!我认为那将是相当昂贵的!如何在Backbone中针对每个帖子执行此操作?即,如何将 View 绑定(bind)到每个单独的li.WCPost?

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

最佳答案

据我所知,在$(event.target).data('postId')函数中使用类似postClicked()的方法是执行此类操作的一种正常方法。

起初,事件的广泛使用可能看起来并不常见,但是如果使用得当,这是改善代码组织的一种好方法。在大多数情况下,尤其是使用jQuery的情况下,您确实可以从事件中获取所需的所有数据。 (请注意,传递给postClicked函数的事件是常规jQuery事件对象,可以应用everything you can find about it。Backbone.js uses jQuery的delegate()函数绑定(bind)事件。)

* * *

但是,您仍然可以在 View 的initialize()方法中自行绑定(bind)事件。

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>)是一个自动将jQuery选择器作用域限定到您的 View 的函数,等效于$(<selector>, this.el)。)

* * *

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

要显示帖子,请在帖子 ListView 中浏览Posts集合,为每个Post实例创建一个 View ,然后将其附加到.listOfPosts元素。

您不再需要解决访问帖子ID的问题,因为您可以将checkbox click事件绑定(bind)到PostView上。因此,在处理程序函数中,可以通过相关模型(this.model.get('id'))或 View 元素($(this.el).data('postId'))轻松找到帖子的ID。

* * * 更新

Now that I generated my posts' DOM independently of Backbone how do I 'retrofit' a view to each post like I mentioned in the question?

I don't want to refactor a ton of client code just to accommodate Backbone. But how do I bind a view to each li??



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

OOP方法相对于基于DOM的一些优势:
  • View 比DOM元素更适合于数据存储。

    请注意,使用当前方法,您将广泛使用data属性,例如,存储帖子的ID。但是,如果您使用的是 View ,则无需这样做:每个PostView已经知道其相关模型,因此您可以通过view.model.get('postId')等轻松获取帖子ID,以及所需的其他任何帖子数据。

    您还可以存储不属于Post模型的特定于 View 的数据:例如,动画和/或显示状态(展开,选中,…)。
  • View 更适合于定义元素的行为。

    例如,如果要为每个帖子指定复选框click事件处理程序,请将此代码放入PostView类中。这样,事件处理程序可以知道所有发布数据,因为 View 可以访问它。而且,代码的结构更好-处理特定帖子,属于PostView且不会妨碍您。

    另一个示例是在 View 上定义render()函数的约定。模板函数或模板字符串存储在 View 属性template中,并且render()渲染该模板,并用结果HTML填充 View 的元素:
    render: function() {
        $(this.el).html(this.template({
            modelData: this.model.toJSON()
        }));
    },
    
  • 操纵DOM可能比操纵对象要慢。

  • 但是,基于DOM的(似乎您到目前为止一直在使用)有自己的优点,尤其是对于不太复杂的应用程序。另请参阅:Object Oriented Javascript vs. Pure jQuery and .data storage

    Is there a way to bind views to current and future DOM elements that are NOT generated by backbone?

    Does that imply that backbone needs to be use from the very start and will be difficult to 'retrofit' so to speak?



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

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

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

    (顺便说一句,我认为至少我应该澄清使用MVC方法的要点:使用后端服务器提供的API,创建本质上最能发挥最大作用的客户端应用程序。为模型提供JSON数据,其余则由客户端应用广泛使用AJAX来完成。如果您在用户与您的网站进行交互时执行正常的页面加载,则这种MVC和繁琐的客户端可能会给您带来负担。是您将不得不重构一些代码,根据您的要求和资源,这可能不是一个选择。)

    关于javascript - 如何将Backbone.View绑定(bind)到DOM中类似元素列表中的 'single' DOM元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6751151/

    有关javascript - 如何将Backbone.View绑定(bind)到DOM中类似元素列表中的 'single' DOM元素的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    4. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

      给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

    6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

      我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

    8. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    9. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

      我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

    10. ruby-on-rails - 渲染另一个 Controller 的 View - 2

      我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

    随机推荐