Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
554 views
in Technique[技术] by (71.8m points)

jqgrid - Browser Memory Usage Comparison: inline onClick vs. using JQuery .bind()

I have ~400 elements on a page that have click events tied to them (4 different types of buttons with 100 instances of each, each type's click events performing the same function but with different parameters).

I need to minimize any impacts on performance that this may have. What kind of performance hit am I taking (memory etc) by binding click events to each of these individually (using JQuery's bind())? Would it be more efficient to have an inline onclick calling the function on each button instead?

Edit for clarification :):
I actually have a table (generated using JQGrid) and each row has data columns followed by 4 icon 'button' columns- delete & three other business functions that make AJAX calls back to the server:

|id|description|__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___data____|____data____|icon|icon|icon|icon|  
| 2|___data____|____data____|icon|icon|icon|icon|   
| 3|___data____|____data____|icon|icon|icon|icon|   
| 4|___data____|____data____|icon|icon|icon|icon|    

I am using JQGrid's custom formatter (http://www.trirand.com/jqgridwsiki/doku.php?id=wiki:custom_formatter) to build the icon 'buttons' in each row (I cannot retrieve button HTML from server).

It is here in my custom formatter function that I can easily just build the icon HTML and code in an inline onclick calling the appropriate functions with the appropriate parameters (data from other columns in that row). I use the data in the row columns as parameters for my functions.

    function removeFormatter(cellvalue, options, rowObject) {       
        return "<img src='img/favoritesAdd.gif' onclick='remove("" + options.rowId + "")' title='Remove' style='cursor:pointer' />";
    }

So, I can think of two options:
1) inline onclick as I explained above
--or--
2) delegate() (as mentioned in below answers (thank you so much!))

  1. Build the icon image (each icon type has its own class name) using the custom formatter.
  2. Set the icon's data() to its parameters in the afterInsertRow JQGrid event.
  3. Apply the delegate() handler to buttons of specific classes (as @KenRedler said below)
>    $('#container').delegate('.your_buttons','click',function(e){  
>      e.preventDefault();  
>      var your_param = $(this).data('something'); // store your params in data, perhaps  
>      do_something_with( your_param );  
>    }); //(code snippet via @KenRedler)

I'm not sure how browser-intensive option #2 is I guess...but I do like keeping the Javascript away from my DOM elements :)

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Because you need not only a general solution with some container objects, but the solution for jqGrid I can suggest you one more way.

The problem is that jqGrid make already some onClick bindings. So you will not spend more resources if you just use existing in jqGrid event handler. Two event handler can be useful for you: onCellSelect and beforeSelectRow. To have mostly close behavior to what you currently have I suggest you to use beforeSelectRow event. It's advantage is that if the user will click on one from your custom buttons the row selection can stay unchanged. With the onCellSelect the row will be first selected and then the onCellSelect event handler called.

You can define the columns with buttons like following

{ name: 'add', width: 18, sortable: false, search: false,
  formatter:function(){
      return "<span class='ui-icon ui-icon-plus'></span>"
  }}

In the code above I do use custom formatter of jqGrid, but without any event binding. The code of

beforeSelectRow: function (rowid, e) {
    var iCol = $.jgrid.getCellIndex(e.target);
    if (iCol >= firstButtonColumnIndex) {
        alert("rowid="+rowid+"
Button name: "+buttonNames[iCol]);
    }

    // prevent row selection if one click on the button
    return (iCol >= firstButtonColumnIndex)? false: true;
}

where firstButtonColumnIndex = 8 and buttonNames = {8:'Add',9:'Edit',10:'Remove',11:'Details'}. In your code you can replace the alert to the corresponding function call.

If you want select the row always on the button click you can simplify the code till the following

onCellSelect: function (rowid,iCol/*,cellcontent,e*/) {
    if (iCol >= firstButtonColumnIndex) {
        alert("rowid="+rowid+"
Button name: "+buttonNames[iCol]);
    }
}

In the way you use one existing click event handler bound to the whole table (see the source code) and just say jqGrid which handle you want to use.

I recommend you additionally always use gridview:true which speed up the building of jqGrid, but which can not be used if you use afterInsertRow function which you considered to use as an option.

You can see the demo here.

UPDATED: One more option which you have is to use formatter:'actions' see the demo prepared for the answer. If you look at the code of the 'actions' formatter is work mostly like your current code if you look at it from the event binding side.

UPDATED 2: The updated version of the code you can see here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...