Делегирование события x-tag: доступ к корневому элементу
Мне нужно делегировать событие "tap" кнопке закрытия в пользовательском элементе, и, в свою очередь, вызвать close()
метод на корневой элемент. Вот пример:
xtag.register('settings-pane', {
lifecycle: {
created: function () {
var tpl = document.getElementById('settings-pane'),
clone = document.importNode(tpl.content, true);
this.appendChild(clone);
}
},
events: {
'tap:delegate(button.close)': function (e) {
rootElement.close(); // <- I don't know the best way to get rootElement
}
},
methods: {
close: function () {
this.classList.add('hidden');
}
}
});
<template id="settings-pane">
<button class="close">✖</button>
</template>
2 ответа
Привет, это автор библиотеки, позвольте мне прояснить это:
Для любого слушателя, установленного вами в DOM, X-Tag или vanilla JS, вы всегда можете использовать стандартное свойство e.currentTarget
чтобы получить доступ к узлу, к которому был прикреплен слушатель. Для X-Tag, используете ли вы delegate
псевдо или нет, e.currentTarget
всегда будет ссылаться на ваш пользовательский элемент:
xtag.register('x-foo', {
content: '<input /><span></span>',
events: {
focus: function(e){
// e.currentTarget === your x-foo element
},
'tap:delegate(span)': function(e){
// e.currentTarget still === your x-foo element
// 'this' reference set to matched span element
}
}
});
Помните, что это стандартный API для доступа к элементу, к которому был прикреплен прослушиватель событий, подробнее здесь: https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
Лучший подход к этой проблеме после нескольких месяцев ее решения - создать еще одно "псевдо", похожее на :delegate()
псевдо, но это вызывает обратный вызов по-другому. Это добавляет :descendant()
псевдо к xtag:
xtag.pseudos.descendant = {
action: function descendantAction(pseudo, event) {
var match,
target = event.target,
origin = target,
root = event.currentTarget;
while (!match && target && target != root) {
if (target.tagName && xtag.matchSelector(target, pseudo.value)) match = target;
target = target.parentNode;
}
if (!match && root.tagName && xtag.matchSelector(root, pseudo.value)) match = root;
return match ? pseudo.listener = pseudo.listener.bind({component: this, target: match, origin: origin}) : null;
}
};
Вы бы использовали это именно так, как вы бы :delegate()
, но this
будет ссылаться на объект, который, в свою очередь, будет ссылаться на целевой элемент (элемент, соответствующий селектору CSS, например, button.close
), источник (элемент, получивший событие) и компонент (сам пользовательский элемент). Пример использования:
xtag.register('settings-pane', {
methods: {
close: function () {
this.classList.add('hidden');
}
},
events: {
'tap:descendant(button.close)': function (e) {
this.origin; // <button> or some descendant thereof that was tapped
this.target; // <button> element
this.component; // <settings-pane> element
this.component.close();
}
}
});