Как отслеживать списки узлов в плагине Jquery (если клиенты могут удалить эти узлы DOM) - PullRequest
8 голосов
/ 22 ноября 2011

Я пишу плагин jQuery, который «указывает» на определенное количество узлов в DOM. Тем не менее, если я пытаюсь что-то вроде того, чтобы мой плагин содержал ссылки на набор узлов, я беспокоюсь о том, что они «устареют».

(Хотя я понимаю, что JavaScript является сборщиком мусора и не будет зависать, я бы хотел иметь возможность обновлять свои списки и не держаться за вещи, которые должны быть в GC)

Первое, что пришло мне в голову, это что-то вроде крючка. Но, похоже, нет стандарта, который выглядит заслуживающим доверия:

Можно ли с помощью JQuery запускать функцию, когда элемент DOM вызывает .remove ()?

Обратный вызов при удалении элемента из дерева DOM?

Обратный вызов jQuery remove ()?

Это заставило меня задуматься о ведении списков узлов, помещая в них атрибут класса. Таким образом, их членство в списке будет сопровождать их. Но, как можно опасаться, перечисление может быть патологически медленным, поэтому вы должны сформулировать свой запрос как теги перед классами .

В дополнение к потенциальным проблемам с производительностью, мне интересно, считается ли плохой формой плагин для размещения классов на узлах DOM для такого рода целей, которые не связаны со стилем. (Одна из лучших особенностей .data() заключается в том, что он относительно внеполосный, и за исключением этой проблемы со списком, это то, что я использую.)

Это кажется достаточно распространенной проблемой, которая решалась другими плагинами. Я испытываю желание использовать решение класса для его свойств «правильности», хотя оно и медленнее. Но есть ли более быстрый и более канонический способ, который дает лучшее из обоих миров?

Ответы [ 2 ]

5 голосов
/ 25 ноября 2011

Я бы поверил в то, как это делает jQuery UI.В частности, Droppables , они поддерживают внутренний список объектов jQuery, которые они перебирают, когда что-то над ним нависает.Они управляют списком двумя способами:

  1. Добавить обработчик уничтожения, который запускается при запуске jQuery.remove ().(Они подключаются к функциям удаления jQuerys, чтобы сделать это) Это не будет обрабатывать обычные удаления javascript, хотя и так,
  2. Просто проверьте, существует ли оно, прежде чем что-либо делать.удалить его, я полагаю, потому что его можно удалить из DOM, а затем вернуть обратно.
1 голос
/ 02 декабря 2011

Извините, что сломал это для вас, но «надежный код на основе jQuery» является противоречием в терминах. FWIW:

jQuery, как и несколько других популярных в настоящее время сред сценариев, создает Array -подобный объект для хранения результата запроса, а не объект, реализующий NodeList интерфейс из W3C DOM Level 2 + Core (NodeList для краткости). A NodeList is live ; Array -подобные объекты, которые являются собственными объектами ECMAScript, а не хост-объектами, (обычно) не являются.

Если вы не используете такие платформы для этого, у вас не будет этой проблемы, поскольку все (квази) стандартные методы DOM (такие как getElementsByClassName()) и свойства (такие как document.forms) возвращают / выдает NodeList (иногда даже HTMLCollection).

События уровня 2 DOM указано типы событий мутации , но по состоянию на События уровня 3 DOM ( Рабочий чертеж ) они устарел , и любые хуки, которые сейчас ненадежны и , вероятно, даже не совместимы .

Таким образом, вы должны использовать (квази) стандартные методы для этого, а не результат jQuery и не события мутации.

Однако, если вы все еще хотите пойти по пути jQuery (-ish) (со всеми другими неявными недостатками), вам следует обратиться к свойству Node parentNode. Node s, которые не являются узлом Document, но все еще находятся в дереве документа, имеют значение свойства не null parentNode (тогда как null следует понимать как язык Базовой спецификации W3C DOM Level 2+) -independent null, поэтому вы должны искать все значения, которые преобразуются в true в реализации ECMAScript). Соответственно, все остальные Node имеют значение свойства parentNode, равное null, поэтому в реализации ECMAScript тип преобразуется в false.

Если предположить, что myNodes относится к экземпляру Array, элементами которого являются Node s, а myNode относится к одному такому объекту узла, то должно работать следующее:

var i = 0;

/* … */

var myNode = myNodes[i];
if (!myNode.parentNode)
{
  myNodes.splice(i, 1);
}

Затем вы можете иногда перебирать myNodes, скажем, в функции, вызываемой через window.setInterval(), и удалять из нее «устаревшие» узлы. Это, конечно, не так хорошо, как с NodeList, но оно работает, даже если узлы удаляются без использования jQuery, и даже если типы событий мутации не поддерживаются средой выполнения.

К сожалению, jQuery() не возвращает ссылку на экземпляр Array. Так что сначала вам нужно будет сделать один, например:

var jqObj = jQuery("…");

/* or jQuery.makeArray(jqObj) */
var a = Array.prototype.slice.call(jqObj, 0);

(Мы используем тот факт, что объект, на который ссылается jqObj, имеет свойство length.)

Я не могу сказать, что было бы хорошим стилем для плагина jQuery, поскольку по причинам, которые должны быть очевидны к настоящему времени, я стараюсь в первую очередь избегать использования jQuery.

Вы также должны научиться различать язык программирования * s *, как JavaScript , и (обычно не зависящие от языка) API, которые можно использовать с ними, например, DOM.

НТН.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...