[Vue-rx] Pass Template Data Through domStreams in Vue.js and RxJS

domStreams enable you to pass additional data along the stream that can be provided by the template (such as data coming from a v-forrendering of an Array). You can then pluck off the data from the stream and use it further down the stream.

<template>
  <section class="section">
    <button class="button" :disabled="disabled$" v-stream:click="{subject: click$, data: 1}">{{buttonText$}}</button>
    <h2>
      {{name$}}
    </h2>
    <img v-stream:error="imageError$" :src="image$" alt="">
  </section>
</template>

<script>
import { from, of, merge, throwError } from 'rxjs';
import {
  exhaustMap,
  switchMap,
  pluck,
  map,
  mapTo,
  catchError,
  shareReplay,
  share,
  startWith
} from 'rxjs/operators';

export default {
  name: 'app',
  domStreams: ['click$', 'imageError$'],
  subscriptions() {
    const createLoader = url => from(this.$http.get(url)).pipe(pluck('data'));

    const luke$ = this.click$.pipe(
      pluck('data'),
      map(id => `https://starwars.egghead.training/people/${id}`),
      exhaustMap(createLoader),
      catchError(() => of({name: 'Failed.. :('})),
      share()
    );

    const name$ = luke$.pipe(pluck('name'));

    const loadImage$ = luke$.pipe(
      pluck('image'),
      map(src => `https://starwars.egghead.training/${src}`)
    );

    const failImage$ = this.imageError$.pipe(
      mapTo(`http://via.placeholder.com/400x400`)
    );

    const image$ = merge(
      loadImage$,
      failImage$
    )

    const disabled$ = merge(
      this.click$.pipe(mapTo(true)),
      luke$.pipe(mapTo(false)),
    ).pipe(startWith(false));

    const buttonText$ = disabled$.pipe(map(b => (b ? 'Loading...' : 'Load')));


    return {
      name$,
      image$,
      failImage$,
      disabled$,
      buttonText$
    };
  }
};
</script>
原文地址:https://www.cnblogs.com/Answer1215/p/9332271.html