Отслеживание кликов; Влияние на производительность при поиске DOM - PullRequest
0 голосов
/ 10 февраля 2011

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

// Once the page is completed loaded
window.mmload(function() {      
    // Get the container object
    obj = document.getElementById(name);

    if ( obj.length < 0 )
        throw ("The Id passed into the tracker does not exist ("+name+")");

    // Find all the elements belonging to the tracking class 
    var trackingClass = new RegExp( /tracking\[[a-zA-Z0-9\.\-_]+\]/g );
    var myElements = getElementsByRegex( trackingClass, obj );

    //For each of those elements...
    for( var i in myElements ) {
        var elm = myElements[i];
        var method = elm.className.match( /tracking\[[a-zA-Z0-9\.\-_]+\]/ )[0].split('[')[1].replace(']','').split('.')[2];
        method = typeof( method ) == 'undefined' ? 'click' : method;

        // Add a click event listener
        myElements[i].addEventListener( method, function(e){
            // Get the element, the link (if any), and the args of the event                
            var link = elm.getAttribute('href') == null ? "" : elm.getAttribute('href');
            var args = elm.className.match( /tracking\[[a-zA-Z0-9\.\-_]+\]/ )[0].split('[')[1].replace(']','').split('.');

            // If a link existed, pause it, for now
            if ( link != '' )
                e.preventDefault();

            // Track the event
            eventTracker( args[0], args[1], ( method == 'click' ? 'redirect' : 'default' ), link );

            return false;
        }, true);
    }
});

Прямо сейчас у меня работает этот кусок кода, когда окно полностью загружено (window.mmload () - это функция, которую я сделал для добавления событий window.onload).Однако, может быть, иногда мне нужно снова запустить эту функцию, потому что я добавил новые элементы в DOM через javascript с этим именем класса и тоже хочу их отслеживать.

Моим первоначальным решением было запустить эту функцию, используяsetInterval для проверки DOM каждые несколько миллисекунд или секунд или что-либо еще, что имеет смысл.Тем не менее, я был обеспокоен тем, что при таком подходе он может замедлить работу веб-сайта, тем более что он работает на мобильном веб-сайте для смартфонов.Я не уверен, какой удар по производительности я мог бы предпринять, если бы часто искал в DOM.

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

Ответы [ 3 ]

1 голос
/ 10 февраля 2011

Вы должны учитывать четное делегирование .

Вы просто добавляете один прослушиватель событий к корню документа и проверяете класс элемента, из которого произошло событие (event.target).Если вы хотите включить также клики от потомков, вам придется пройти DOM вверх от цели и проверить, содержит ли какой-либо из предков класс.

Я вижу два основных преимущества:

  • Он работает для вновь сгенерированных элементов без каких-либо дополнительных шагов (поэтому другие разработчики не должны делать ничего особенного).
  • Он добавляет только один обработчик событий вместо потенциальномногие, что экономит память.

Недостатки:

  • Если вдоль пути зарегистрированы другие обработчики событий, и они предотвращают всплывающее событие, вы не можете зарегистрировать это событие.

Немного больше информации:

Обработчик событий получает объект event в качестве первого аргумента.Этот объект имеет несколько свойств , среди прочего, , который элемент, из которого происходит событие, имеет форму .

Например, чтобы получить целевой элемент:

var element = event.target || event.srcElement;

Это будет элемент DOM, и вы можете получить доступ к классам через element.className.

Таким образом, ваш прослушиватель событий может выглядеть следующим образом (обратите внимание, что IE использует другой метод для подключения прослушивателей событий иобъект события не передается, но доступен через window.event):

function handler(event) {
    event = event || window.event;
    var target = event.target || event.srcElement;
    if(target.className.match(/tracking\[[a-zA-Z0-9\.\-_]+\]/g) {
        // do your stuff
    }
}

if(document.addEventListener) {
   document.addEventListener('click', handler, false);
}
else {
   document.attachEvent('onclick', handler);
}

Но, как я уже сказал, это будет пропускать события, которые не могут всплыть.По крайней мере, в браузерах, следующих за моделью W3C (а не в IE), вы можете обрабатывать события в фазе захвата , установив для последнего параметра значение true:

document.addEventListener('click', handler, true);
0 голосов
/ 10 февраля 2011

Третий вариант - написать метод для манипулирования innerHTML элемента. В конце этого метода просто вызовите вашу функцию, которая обновляет все.

пример:

var setHtml = function(element, newHtml){
     element.innerhtml = newHtml;
     yourRefreshFunction();
}

Очевидно, что для этого необходимо, чтобы ваши веб-разработчики использовали этот метод для обновления домена. И вам придется сделать это для всего, что является более сложным, чем простое редактирование HTML. Но это дает вам идею.

Надеюсь, это поможет!

0 голосов
/ 10 февраля 2011

Если вы можете жить без IE, то существует событие change, к которому вы можете подключиться для элемента window / document / dom. Просто подключитесь к событию на уровне документа, и оно будет срабатывать каждый раз, когда что-то изменяется на странице (материал вставлен, удален, изменен). Я полагаю, что контекст события содержит то, что изменилось, поэтому было бы довольно просто найти любые новые отслеживаемые элементы и прикрепить к нему свой шпионский код.

...