Перемещение большого набора объектов HTML на странице и повторное связывание событий с помощью jQuery.

У меня есть DIV со многими элементами, которые кликабельны. Каждый со своим уникальным событием. Этот DIV имеет «закрепленный» режим, в котором он отображается в другом месте и макете на странице, когда режим переключается.

Я должен отметить, что мой основной целевой браузер — IE8. Многие из проблем, с которыми я здесь сталкиваюсь (SSSLLLLLOOOOWWWWW), просто исчезают, когда я тестирую Chrome.

Я пытался использовать метод $(...).html() для перемещения содержимого HTML в новое место. Это работает, но события теряются. Я могу использовать .live() вместо .bind(), но это делает все ответы на события примерно в 10 раз медленнее (помните, что в этом DIV у меня МНОГО элементов).

Еще одна вещь, которую я пробовал, - это просто создавать контент в обоих DIV и привязывать события к обоим. Затем я могу переключить видимость основного DIV. Это сделало создание DOM намного медленнее, чем раньше (все еще мгновение в Chrome, но не в IE).

Я ищу «классический» способ (если он существует) для выполнения этого перемещения контента на странице, сохраняя при этом события нетронутыми.

ОБНОВЛЕНИЕ Думайте об этом стыковочном действии как о чем-то похожем на стыковку плавающего окна с одной стороной экрана в Visual Studio.


person Ron Harlev    schedule 11.02.2010    source источник
comment
будет ли содержимое отображаться несколько раз одновременно?   -  person Soufiane Hassou    schedule 11.02.2010
comment
Нет. Или или. Один будет скрыт, когда другой будет показан.   -  person Ron Harlev    schedule 11.02.2010


Ответы (3)


Если вы используете jquery 1.4, вы можете использовать detach:

The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.
<body>
    <div id='container1'>...elements with bound events...</div>
    <div id='container2'></div>
</body>
<script>
    var divs = $("#container1").children().detach(); // removes the node from the DOM
    $("#container2").empty().append(divs);
</script>

или используйте clone(true), если вы хотите, чтобы оба div отображались одновременно:

var divs = $("#container1").clone(true);
$("#container2").empty().append(divs);

О том, что $.fn.live() слишком медленный:
Вы можете попробовать изменить "live", чтобы сделать его немного более эффективным, чтобы он работал следующим образом:

// $.live(selector,    context,         event,   fn);
   $.live("a.explode", "div.container", "click", function(){
       alert("boom"); return false;
   });

Что это должно сделать, так это привязать тип события к элементу контекста БЕЗ поиска элементов селектора в первую очередь. Не знаю, будет ли это полезно в вашем случае, но я подумал, что стоит упомянуть.

Чтобы еще больше ускорить процесс, используйте mousedown вместо клика:

$("a").mousedown(function(){
    // do stuff...
}).click(function(){return false;});
person David Murdoch    schedule 11.02.2010
comment
Спасибо. .detach() работает отлично. Спасибо за отличный обзор вариантов. Отличная информация. Я бы проголосовал не раз, если бы это было возможно :) - person Ron Harlev; 11.02.2010

Если вас беспокоит медлительность, вы можете просто использовать css и переместить div туда, куда хотите?

person Soufiane Hassou    schedule 11.02.2010

Если у вас есть куча элементов, к которым нужно привязать события, то наиболее эффективным способом является использование делегирования событий. .live() будет работать, но, как вы видели, это может быть медленным со многими элементами.

Вот простой пример прослушивания события клика внутри div и проверки того, вызвала ли его якорь:

$("#container").click(function(e) {

  var $target = $(e.target);
  if ($target.is("a")) {
    // do some
  }

});
person ScottE    schedule 11.02.2010
comment
Обратите внимание, что в некоторых случаях лучше использовать $target.closest(a,this)[0] вместо $target.is(a) может. - person David Murdoch; 11.02.2010