简体   繁体   English

Backbone视图中的事件,可以在应用程序中多次添加

[英]Events in a Backbone view that can be added multiple times in the application

Before explaining the problem I am facing,this is the code I am using: 在解释我面临的问题之前,这是我正在使用的代码:

<!DOCTYPE HTML>
<html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
        <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
        <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
        <script type="text/template" id="view_template">
            <li>
            <label class="lbl" style="width:100px;display:inline-block;"><%= name %></label>
            <button class="btn">Click</button>
            </li>
        </script>
        <script type="text/javascript">
            AppModel = Backbone.Model.extend({
                defaults : {
                    m_name : "Default name"
                },
                modify : function(value) {
                    this.set({
                        m_name : value
                    });
                }
            });

            $(document).ready(function() {
                $("#add").click(function() {
                    var appModel = new AppModel();
                    appModel.modify($("#txt").val());
                    new CustomView({
                        model : appModel
                    });
                    $("#txt").val("");
                });
                CustomView = Backbone.View.extend({
                    el : $(".list"),
                    events : {
                        "click .btn" : "showAlert"
                    },
                    initialize : function() {
                        this.render();
                    },
                    render : function() {
                        var variables = {
                            name : this.model.get("m_name")
                        };
                        var t = _.template($("#view_template").html(), variables);
                        $(this.el).append(t);
                    },
                    showAlert : function() {
                        alert(this.model.get("m_name"));
                    }
                });
            });

        </script>
    </head>
    <body>
        <input type="text" id="txt"/>
        <button id="add">
            Add
        </button>
        <ul class="list" style="list-style: none"></ul>
    </body>
</html>

A demo is here - http://jsfiddle.net/jCekv/ 这里有一个演示 - http://jsfiddle.net/jCekv/

You can type any value into textfield and click Add.The text will be added to a list which is a backbone view.You can keep on adding multiple values to the list.After adding some items,click on the Click button in any of the items in the list.I want to get the value in the model for that view.But because of the way I am adding Events ,event handlers are getting executed multiple times.For eg:If i add 3 items and click on any of the buttons in the list 3 alerts will come-one corresponding to each of the items that is added.This is not the way I want.I want to have the event being triggered only for the Backbone View which has been clicked so that I get access to the model of the Backbone View I have clicked. 您可以在文本字段中键入任意值,然后单击“添加”。文本将添加到作为骨干视图的列表中。您可以继续向列表中添加多个值。添加一些项目后,单击任何一个中的“单击”按钮。列表中的项目。我想获取该视图的模型中的值。但由于我添加Events的方式,事件处理程序正在执行多次。例如:如果我添加3项并单击任何一项列表中的按钮3将出现一个警报 - 一个对应于添加的每个项目。这不是我想要的方式。我希望仅针对已单击的Backbone View触发事件,以便我可以访问我点击了Backbone View的模型。

How I can achieve this functionality?.Please let me know if my question is not clear.Thanks in advance. 我如何才能实现这一功能?。如果我的问题不明确,请告诉我。谢谢。

The problem is that all your CustomViews have their element set to $(".list") . 问题是所有的CustomViews都将其元素设置为$(".list") Therefore, all delegate events are added to the same DOM element, the list, and not the individual list items. 因此,所有委托事件都添加到相同的DOM元素,列表,而不是单个列表项。

See a possible solution here: http://jsfiddle.net/mbuchetics/R8jPA/ 请在此处查看可能的解决方案: http//jsfiddle.net/mbuchetics/R8jPA/

I changed the CustomView to use a tagName of li instead of setting the element. 我更改了CustomView以使用litagName而不是设置元素。 The template is not appended to the element but instead its content is set. 模板不会附加到元素,而是设置其内容。 This way, each CustomView represents one item of the list and the click event refers to exactly that item. 这样,每个CustomView代表列表中的一个项目,而click事件恰好指的是该项目。 I also removed the render call from initialize, instead the view is rendered when it is appended to the list (in the "add click" callback). 我还从初始化中删除了渲染调用,而是在将视图附加到列表时(在“添加单击”回调中)呈现视图。 Render() returns this and therefore you can use view.render().el to get the list item's html. Render()返回this ,因此您可以使用view.render().el来获取列表项的html。

You could further improve your application to use collections and a separate view for the collection. 您可以进一步改进应用程序以使用集合和集合的单独视图。 The collection view could then handle events such as "add" on the collection and update itself (and the individual item views) accordingly. 然后,集合视图可以处理集合上的“添加”等事件,并相应地更新自身(以及各个项目视图)。

This is because you're creating a new instance of the view class for each item, assigning the same DOM element (which corresponds to the whole list, not an individual item) to each instance, and registering the same event listener. 这是因为您正在为每个项创建视图类的新实例,为每个实例分配相同的DOM元素(对应于整个列表,而不是单个项),并注册相同的事件侦听器。 So each time you click any of the buttons, the event listener fires for each view object. 因此,每次单击任何按钮时,事件侦听器都会为每个视图对象触发。

Something like this will work: 这样的东西会起作用:

http://jsfiddle.net/jCekv/1/ http://jsfiddle.net/jCekv/1/

$( document ).ready( function () {

  $( "#add" ).click( function () {

    var appModel = new AppModel();

    appModel.modify( $( "#txt" ).val() );

    var item = new Item_View( {

      model : appModel

    } );

    list.add_item( item );

    $( "#txt" ).val( "" );

  } );


  var List_View = Backbone.View.extend( {

    el : $( ".list" ),

    events : {

      "click .btn" : "showAlert"

    },

    initialize : function () {

      this.render();

    },

    add_item : function ( item ) {

      item.render();

      item.$el.data( 'view_object', item );

      this.$el.append( item.el );

    },

    showAlert : function ( event ) {

      alert(

        $( event.target )

          .closest( 'li' )

          .data( 'view_object' )

          .model.get( "m_name" )

      );

    }

  } );


  var Item_View = Backbone.View.extend( {

    tagName : 'li',

    render : function() {

      var variables = {

        name : this.model.get( "m_name" )

      };

      var t = _.template( $( "#view_template" ).html(), variables );

      this.$el.html( $( t ).html() );

      return this;

    }

  } );


  var list = new List_View;

} );
  • I created separate view classes for the list and for items. 我为列表和项目创建了单独的视图类。

  • I'm storing a reference to the view object for each item using jQuery.data , so that the view object (and via that, the model object) can be retrieved inside the event listener ( showAlert ). 我正在使用jQuery.data存储对每个项目的视图对象的引用,以便可以在事件侦听器( showAlert )中检索视图对象(以及通过它,模型对象)。 Alternatively you could maintain an array of the items' view objects in the list view. 或者,您可以在列表视图中维护项目视图对象的数组。 I already have this setup to perform adding items through an add_item method of the list view, so that would facilitate maintaining such an array of item view objects. 我已经有了这个设置来通过列表视图的add_item方法执行添加项目,这样便于维护这样的项目视图对象数组。

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

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