RiotJS - Как передавать события между вложенными тегами, используя шаблон Observable?
Я не совсем уверен, правильно ли я понимаю, как работают наблюдаемые и как получить ссылки из смонтированных тегов. У меня есть компонент. В этом компоненте у нас есть компонент и компонент. Цель состоит в том, чтобы избежать связи между компонентами. В связи с этим мне бы хотелось, чтобы мой поисковый компонент инициировал событие, когда поиск будет выполнен (нажата кнопка). Это событие должно быть перехвачено компонентом, который будет фильтровать данные коллекции на основе поиска.
Файл index.html загружает тег с помощью:
index.html
riot.mount(".content", "page", null);
Страница определяется следующим образом:
page.js
<page>
<!-- Search tag controls -->
<search id="searchTag"></search>
<!-- Collection data to display -->
<collection id="collectionTag"></collection>
</page>
Сценарий компонента кратко определен так:
search.js
var self = this;
riot.observable(self);
<!-- This function is called when the user click on the button. -->
self.filtering = function()
{
<!-- We get data from inputs -->
var info = Getting data from inputs;
<!-- Trigger the event hoping that someone will observe it -->
self.trigger("filterEvent", info);
}
Как я могу заставить компонент наблюдать за этим событием?
Мне кажется, что я должен быть в состоянии получить ссылки из тега поиска и тега коллекции в page.js. Таким образом я мог связать события следующим образом:
searchComponent = riot.mount('search');
collectionComponent = riot.mount('collection');
searchComponent.on('filterEvent', function()
{
<!-- Trigger function to filter collection data -->
collectionComponent.trigger('filterData');
});
Прямо сейчас я не могу заставить это работать так.
В момент выполнения searchComponent и collectionComponent не определены.
Я попытался также получить ссылки на этот компонент с помощью this.searchTag
а также this.collectionTag
вместо того, чтобы монтировать их, но во время выполнения кода компоненты не были смонтированы, и поэтому я не получаю ссылки на них.
Какие-нибудь идеи, чтобы заставить это работать?
5 ответов
Во-первых, я не понимаю вашу файловую структуру!
На вашем месте я бы поменял имена файлов:
page.js -> page.tag
search.js -> search.tag
И я не вижу ваш поисковый тег в коде search.js.
Так что я не вижу ваш файл тегов коллекции...
Вы уверены, что этот использует этот код?riot.observable({self|this});
Потому что именно он получит Событие.
Для меня, когда я использую Riot.js(2.2.2) в моем браузере, если я использую searchComponent = riot.mount('search');
searchComponent будет неопределенным
Но с этим кодом вы можете сохранить ссылку на тэг:
var searchComponent ={};
riot.compile(function() {
searchComponent = riot.mount('search')[0];
});
Попробуйте передать общую наблюдаемую информацию обоим тегам.
var sharedObservable = riot.observable();
riot.mount('search', {observable: sharedObservable}); // the second argument will be used as opts
riot.mount('collection', {observable: sharedObservable});
А затем в тегах просто используйте его:
this.opts.observable.trigger('myEvent');
this.opts.observable.on('myEvent', function() { ... });
РЕДАКТИРОВАТЬ: Или даже лучше, так как ваш search
а также collection
теги являются дочерними тегами другого бунта (page
) (и, следовательно, вам также не нужно монтировать их вручную), вы можете использовать родителя в качестве разделяемой наблюдаемой. Так что просто запускайте или обрабатывайте события в ваших дочерних тегах следующим образом:
this.parent.trigger('myEvent');
this.parent.on('myEvent', function() { ... });
Вдохновленный ответом @gius, теперь это мой предпочтительный метод отправки событий в RiotJS из одного тега в другой... и с ним приятно работать!
Отличие от подхода @gius заключается в том, что если вы используете много вложенных тегов, передача общего Observable для каждого тега не дотягивает, потому что вам придется передавать его снова и снова каждому дочернему тегу (или вызывать из дочерних тегов с грязными вызовами this.parent).
Определение простого миксина, подобного этому (ниже), который просто определяет Observable, означает, что теперь вы можете поделиться этим в любом теге, который хотите.
var SharedMixin = {
observable: riot.observable()
};
Добавьте эту строку в ваши теги..
this.mixin(SharedMixin);
И теперь любой тег, который содержит вышеуказанную строку, может вызывать события, подобные..
this.observable.trigger('event_of_mine');
..или получать такие события..
this.observable.on('event_of_mine',doSomeStuff());
Смотрите мой рабочий jsfiddle здесь http://jsfiddle.net/3b32yqb1/5/.
Другой вариант - использовать глобальные наблюдаемые, что, вероятно, не всегда является наилучшей практикой. Мы используем встроенные в Riot условные выражения для монтирования тегов при определенных условиях, а не для непосредственного монтирования их через JS. Это означает, что теги не зависят друг от друга.
Например, одна наблюдаемая может использоваться для управления всеми коммуникациями. Сам по себе это не полезный пример, он просто демонстрирует технику.
Например, в простом файле JS, таком как main.js
:
var myApp = riot.observable();
Один файл тега может вызвать обновление.
var self = this;
message = self.message;
myApp.trigger('NewMessage', message);
Любое количество других файлов тегов может прослушивать обновления:
myApp.on('NewMessage', function(message) {
// Do something with the new message "message"
console.log('Message received: ' + message);
});
Может быть, излишне, но просто. позволять riot
самонаблюдаемый
riot.observable(riot);
Так что вы можете использовать
riot.on('someEvent', () => {
// doing something
});
в теге, и
riot.trigger('someEvent');
в другой.
Это не хорошо использовать глобальную переменную, но использовать уже существует, может быть приемлемым.