Вопрос:

Javascript equivalent to $.on

javascript jquery

8435 просмотра

4 ответа

457 Репутация автора

As somebody who (unfortunately) learned more of jQuery than raw javascript I am just now taking the time to replace all of my code with raw javascript. No, it's not needed, but it's an easier way for me to learn. A problem I am facing is converting all of my $(document).on with raw javascript. My website is a "single-page application" and most of my actual HTML is in different files which are called via Ajax requests. So, my question is, how would I look for an event fired from dynamically loaded content? I am assuming I would have to add an onclick event to them, but how is it that jQuery does it without needing an onclick event?

Автор: Polarize Источник Размещён: 17.06.2015 01:09

Ответы (4)


13 плюса

26008 Репутация автора

Вот Javascript эквивалент дляon()

JQuery

$(document).on('click', '#my-id', callback);

function callback(){
   ...handler code here
}

Javascript

document.addEventListener('click', function(event) {
    if (event.target.id == 'my-id') {
      callback();
    }
});
function callback(){
   ...handler code here
}

При таком подходе идея состоит в том, чтобы использовать event.target . Конечно, по мере изменения селектора ваш код будет становиться все более вовлеченным

Автор: AmmarCSE Размещён: 17.06.2015 01:15

36 плюса

0 Репутация автора

Решение

Binding handlers in native API is done using addEventListener().

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

function delegate(el, evt, sel, handler) {
    el.addEventListener(evt, function(event) {
        var t = event.target;
        while (t && t !== this) {
            if (t.matches(sel)) {
                handler.call(t, event);
            }
            t = t.parentNode;
        }
    });
}

Вероятно, необходимо сделать некоторые изменения, но в основном это функция, которая берет элемент для привязки, например document, к типу события, селектору и обработчику.

Он начинается e.targetи пересекает родителей, пока не достигнет связанного элемента. Каждый раз он проверяет, соответствует ли текущий элемент селектору, и, если это так, он вызывает обработчик.

Так что вы бы назвали это так:

delegate(document, "click", ".some_elem", function(event) {
    this.style.border = "2px dashed orange";
});

Вот живая демонстрация, которая также добавляет динамические элементы, чтобы показать, что новые элементы также подобраны.

function delegate(el, evt, sel, handler) {
    el.addEventListener(evt, function(event) {
        var t = event.target;
        while (t && t !== this) {
            if (t.matches(sel)) {
                handler.call(t, event);
            }
            t = t.parentNode;
        }
    });
}

delegate(document, "click", ".some_elem", function(event) {
    this.parentNode.appendChild(this.cloneNode(true));
    this.style.border = "2px dashed orange";
});
<div>
  <p class="some_elem">
    <span>
      CLICK ME
    </span>
  </p>
</div>


Вот прокладка, чтобы добавить немного больше поддержки .matches().

if (!Element.prototype.matches) {
  Element.prototype.matches = 
    Element.prototype.matchesSelector || 
    Element.prototype.webkitMatchesSelector ||
    Element.prototype.mozMatchesSelector ||
    Element.prototype.msMatchesSelector || 
    Element.prototype.oMatchesSelector || 
    function(s) {
        var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i = matches.length;
        while (--i >= 0 && matches.item(i) !== this) {}
        return i > -1;            
    };
}
Автор: user1106925 Размещён: 17.06.2015 01:16

3 плюса

8249 Репутация автора

В современных браузерах вы можете использовать его Element.closest()для упрощения репликации метода jQuery, .on()а также для того, чтобы захватывать всплывающие события от дочерних элементов целевого элемента (нюанс, который пропускают некоторые другие реализации). В старых браузерах, включая IE, для этого потребуется полифилл .

const on = (element, event, selector, handler) => {
  element.addEventListener(event, e => {
    if (e.target.closest(selector)) {
      handler(e);
    }
  });
}

on(document, 'click', '#test', e => {
  console.log('click');
});
<button id="test">
  Clickable
  <i>Also Clickable</i>
</button>

Автор: benvc Размещён: 12.06.2019 09:59

0 плюса

5801 Репутация автора

Другой подход для современных браузеров будет выглядеть примерно так:

const on = (selector, event, handler, element=document) => {
  element.addEventListener(event, (e) => { if(e.target.matches(selector)) handler(e); });
};
// click will work for each selector
on('[type="button"], .test, #test','click',  e => {
  alert(e.target.innerHTML);
});
// click event will work for nested .test3 element only
on('.test3','click',  e => {
  alert(e.target.innerHTML);
},document.querySelector('.test2'));
<div id="test">
test
</div>

<div class="test">
test 1
</div>
<div class="test">
test 2
</div>

<button type="button">
go
</button>

<div class="test3">
test 3 outer
</div>


<div class="test2">
<div class="test3">
test 3 inner
</div>
test 2
</div>

Автор: Peter Darmis Размещён: 13.07.2019 03:35
Вопросы из категории :
32x32