Перехват событий щелчка через барьер Shadow DOM

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

$('#main').on('click', 'a[href]', function(e) {
  if (e.which == 2 || e.metaKey) return; // don't capture new tab clicks
  /* stuff */
});

Однако недавно я начал использовать Custom Elements и Shadow DOM. Приведенный выше код не работает с тегами a, которые находятся в теневых деревьях, поскольку событие клика перенаправляется на теневой хост.

Можно ли заставить приведенный выше код работать, чтобы перехватывать события кликов, происходящие в теневом дереве? Если нет, то как лучше всего использовать эту функциональность?

Примечание. Я использую Polymer Platform для полифилла веб-компонентов (хотя и не полностью Polymer).


person Yuri Sulyma    schedule 17.07.2014    source источник
comment
Вот воспроизводимый тестовый пример   -  person CletusW    schedule 18.07.2014


Ответы (3)


В Polymer ≥0.4.0 вы можете использовать комбинатор /deep/:

$('#main').on('click', '* /deep/ a[href]', function() {
  if (e.which == 2 || e.metaKey) return; // don't capture new tab clicks
  /* stuff */
});

Примечание. Этот метод следует использовать с осторожностью, так как он может привести к ошибкам при реализации всех компонентов, включая некоторые части веб-платформы, такие как теги <video>.

person Peter Burns    schedule 17.07.2014
comment
Основная проблема заключается в том, что вы регистрируете обработчик кликов для каждого отдельного тега <a> вместо использования делегирования событий. Это сработает, но, вероятно, неэффективно. - person CletusW; 18.07.2014
comment
Хорошая точка зрения. Из краткого изучения похоже, что jQuery не задыхается от /deep/, как я ожидал, так что, возможно, вы также можете сделать это идиоматическим способом jquery с делегированием. - person Peter Burns; 18.07.2014
comment
Я думаю, что это может быть нормально, так как я проверяю URL-адрес, чтобы убедиться, что это HTTP (S), а не ссылка на фрагмент и т. д. Так что это не должно нарушать функциональность «видео». - person Yuri Sulyma; 18.07.2014
comment
Я обновил его, чтобы он более точно соответствовал исходному вопросу, а также для работы с собственными и неродными реализациями теневого дома. - person Peter Burns; 18.07.2014
comment
Это не работает, когда window.ShadowDOMPolyfill правдив (т.е. в Polymer Platform) - person Yuri Sulyma; 28.07.2014
comment
Платформа Polymer ›=0.4.0 теперь включает полифиллированную реализацию для /deep/ — github.com/ Полимер/ShadowDOM/commit/13e334d - person Peter Burns; 31.08.2014

Вместо того, чтобы ломать существующую структуру, чтобы заставить ее работать как одностраничное приложение, вы можете с самого начала спроектировать ее таким образом. Это даст вам большую часть удивительности веб-компонента. Вот демонстрацияsource) одностраничного приложения, использующего Polymer. Даже если вы не хотите использовать Polymer, вы, вероятно, можете использовать flatiron-director для выполнения того же самого.

person CletusW    schedule 17.07.2014
comment
Вот как я с самого начала проектировал его таким образом, чтобы он был SPA? Большая часть страницы (включая пользовательские элементы) — это пользовательский контент, поэтому я не могу контролировать разметку. Эта демонстрация не работает для меня в Firefox. - person Yuri Sulyma; 18.07.2014
comment
Хорошая точка зрения. Если это пользовательский контент, вы можете застрять с ответом Питера. - person CletusW; 18.07.2014

Возможно, вы захотите использовать core-ajax. для обработки ваших вызовов ajax и некоторой формы межкомпонентного взаимодействия для обновления пользовательского элемента.

person Renaud    schedule 28.07.2014
comment
Это не вопрос о Полимере. Речь идет о ShadowDOM/веб-компонентах, которые полифиллируются Polymer Platform. - person Yuri Sulyma; 29.07.2014