Как связать событие с элементами DOM, созданными с помощью пользовательского тега JsRender?
Прямо сейчас я привязываю события к родительскому элементу визуализируемого содержимого моего пользовательского тега, а затем использую классы для нацеливания события на элемент, который фактически отображает мой пользовательский тег. Я чувствую, что это может вызвать странные ошибки. Например, если кто-то из моей команды поместит два пользовательских тега, использующих одни и те же классы таргетинга, в один и тот же непосредственный родительский элемент, это вызовет срабатывание нескольких событий, связанных с неправильными элементами.
Вот пример кода, который я сейчас использую:
$.views.tags({
toggleProp: {
template: '<span class="toggle">{{include tmpl=#content/}}</span>',
onAfterLink: function () {
var prop = this.tagCtx.view.data;
$(this.parentElem).on('click', '.toggle', function () {
prop.value(!prop.value());
});
},
onDispose: function () {
$(this.parentElem).off('click', '.toggle');
}
}
// ... other custom tags simply follow the same pattern ...
});
К тому времени, когда мы ударили onAfterLink
Есть ли надежный способ доступа к визуализированному элементу DOM (или элементам DOM), соответствующему самому пользовательскому тегу? Без риска поразить неправильный элемент по ошибке? Я понимаю, что пользовательский тег может быть текстом без HTML-элемента, но он все равно будет текстовым узлом, верно? (Могу ли я даже связать события с текстовыми узлами?)
В других местах, используя (далеко) более старые версии JsViews, я связывал события после рендеринга, используя (иногда очень много) целевую логику, встроенную в визуализированные элементы, как data-
атрибутов. Мало того, что это гораздо более хрупкий метод доступа к визуализированным данным, чем мне нравится, было бы невероятно рискованно и запутанно пытаться применить этот подход к некоторым из наших глубоко вложенных и собираемых коллекцией шаблонов.
Мне также не нравится вставлять span
с моим пользовательским тегом, просто чтобы я мог применять классы к нему, но если это все еще необходимо для события, я справлюсь.
Тогда я спрашиваю, каков безопасный модульный способ привязки событий к DOM, чтобы у меня также был доступ к данным, отображаемым непосредственно для этих элементов?
Изменить: В качестве дополнительной проблемы, используя onAfterLink
не позволяет мне связывать события с визуализированным контентом, не связанным с данными. Это может быть частью замысла JsViews против чистого JsRender, но я пока не понимаю, почему это так.
1 ответ
Вместо того чтобы использовать this.parentElem, вы можете использовать
this.contents()
который является объектом jQuery, содержащим все непосредственные элементы содержимого в теге.
Вы также можете предоставить аргумент селектора,
this.contents("someselector")
"фильтровать" и включать необязательный логический "глубокий" флаг для обоих "фильтровать" и "находить" - т.е.
this.contents("someselector", true)
,
Использование вышеуказанных API-интерфейсов гарантирует, что вы берете только те элементы, которые фактически находятся внутри содержимого тега.
Вам может не понадобиться удалять обработчики в onDispose. Если тег удаляется только вместе с его содержимым, вы можете полагаться на тот факт, что jQuery будет располагать обработчиками при удалении элементов из DOM.
Вы можете прикреплять события только к элементам, а не к текстовым узлам. Поэтому, если ваш контент не содержит элементов, вам нужно добавить элемент-обертку, но не иначе.
$.views.tags({
toggleProp: {
template: '{{include tmpl=#content/}}',
onAfterLink: function () {
var prop = this.tagCtx.view.data;
this.contents().on('click', function () {
prop.value(!prop.value());
});
},
onDispose: function () {
this.contents().off('click');
}
}
});
Также взгляните на примеры, такие как http://www.jsviews.com/ которых используется вышеуказанный подход.