Как использовать Rx.Observable.fromEvent в элементе, который еще не существует в DOM? - PullRequest
0 голосов
/ 02 октября 2018

С обычными JS и Jquery вы можете сделать что-то вроде $(document).on('click', '#id', function () { // whatever }).Это позволяет нам добавить событие в элемент, который может еще не существовать в DOM.Я хотел бы использовать Rx.Observable.fromEvent(ele, 'click'), чтобы сделать то же самое - мне нужно сделать это, потому что элементы создаются в другом потоке.Возможно ли это?


КОНТЕКСТ

Какой-то контекст того, чего я пытаюсь достичь.Я слежу за введением в реактивное программирование, которое вы пропустили .Предлагаемое упражнение:

  1. Извлечение пользователей из GitHub API
  2. Отображение трех пользователей в качестве рекомендаций, которым нужно следовать;
  3. У каждого пользователя должна быть кнопка «Удалить»;
  4. Всякий раз, когда нажимается кнопка удаления, удалите это предложение и загрузите еще одно из буфера;

Это очень хорошо до части загрузки трех предложений.Например:

Rx.Observable
    .fromEvent($('#refresh'), 'click')
    .startWith('start up click')
    .map(() => Math.floor(Math.random() * 500))
    .map(offset => `${GITHUB_API}?since=${offset}`)
    .map(url => jQuery.getJSON(url))
    .flatMap(promisse => Rx.Observable.from(promisse))
    .map(users => users.slice(0, 3))
    .do(_ => $('#users').empty())
    .flatMap(users => users)
    .map(user => createItem(user))
    .subscribe(user => $('#users').append(user));

// Just an example for creating the elements
function createItem(user, idx) {
  return $(`
    <li class="item-wrapper horizontal" >
      <img src="${user.avatar_url}" class="rounded-circle" width="50" height="50">

      <div class="item-infos-wrapper vertical">
        <span class="font-weight-bold">${user.login}</span>
        <span class="font-weight-normal">What can we put in here?</span>
      </div>

      <button id="close${idx}" type="button" class="btn btn-outline-danger btn-sm item-action">remove</button>
    </li>
  `);
}

Из того, что я понял из вышеупомянутой статьи, идея обработки удаления элемента состоит в том, чтобы использовать combineLatest с потоком "click button click" и "requestStream" (содержащимрезультаты API), подача объединенных данных в канал, который создает элементы.Моя текущая проблема состоит в том, чтобы создать эту ретроспективную подачу из потока нажатия кнопки «Удалить» и потока запросов в потребителя, который создает элементы.

1 Ответ

0 голосов
/ 02 октября 2018

Вы могли бы сделать что-то подобное, но мне не ясно, откуда взялся idx.Это свойство пользователя?

Rx.Observable
    .fromEvent($('#refresh'), 'click')
    .startWith('start up click')
    .map(() => Math.floor(Math.random() * 500))
    .map(offset => `${GITHUB_API}?since=${offset}`)
    .map(url => jQuery.getJSON(url))
    .flatMap(promisse => Rx.Observable.from(promisse))
    .map(users => users.slice(0, 3))
    .do(_ => $('#users').empty())
    .flatMap(users => users)
    .map(user => createItem(user)) //at this point we have a listItem in the stream

    // from this point it's changed

    .tap(listItem => $('#users').append(listItem)) //append to users, but keep the listItem in the stream
    .map(listItem => $(listItem).find('button')[0]) //get the button element
    .mergemMap(closeButton => fromEvent(closeButton, 'click')) //subscribe to click on the button and merge all the clicks into one stream
    .subscribe((event: MouseEvent) => {
        console.log('clicked', event); //a close button was clicked...
    });

и вот способ удаления li при нажатии кнопки:

Rx.Observable
    .fromEvent($('#refresh'), 'click')
    .startWith('start up click')
    .map(() => Math.floor(Math.random() * 500))
    .map(offset => `${GITHUB_API}?since=${offset}`)
    .map(url => jQuery.getJSON(url))
    .flatMap(promisse => Rx.Observable.from(promisse))
    .map(users => users.slice(0, 3))
    .do(_ => $('#users').empty())
    .flatMap(users => users)
    .mergeMap(user => {
        const listItem = createItem(user);
        $('#users').append(listItem);

        const closeButton = $(listItem).find('button')[0];
        return Rx.Observable.fromEvent(closeButton, 'click').first().tap(_ => listItem.remove());
    })
    .subscribe();
...