Практика RxJS, как интегрировать Vue RxJS

внешний интерфейс Vue.js Parcel RxJS

один,

В этой статье не будет объясняться принцип RxJS, только как интегрировать RxJS в vue.

1,Освоение RxJS за 30 дней

Это руководство по RxJS, написанное тайваньским разработчиком, включает в себя принципиальный анализ, простую реализацию и знакомство с распространенными операторами.

2,Изучите операторы RxJS

Функции и примеры различных распространенных операторов можно просмотреть вместе с официальной документацией RxJS.

2. Vue просто интегрирует RxJS

Чтобы использовать RxJS в Vue, вам нужны только следующие ссылки.Конечно, дополнительные справочные методы могут ссылаться на официальные документы, такие как импорт по требованию.

import Rx from 'rxjs/Rx'
如果你想在vue中使用RxJS的体验更好,这里推荐使用vue-rx这个官方维护的库,使用如下:
import Vue from 'vue'
import VueRx from 'vue-rx'
import Rx from 'rxjs/Rx'

Vue.use(VueRx, Rx)

Таким образом, к экземпляру Vue будет добавлена ​​функция хука подписок.Ее использование аналогично данным, и использование выглядит следующим образом:

<template>
    <div>
        <span>姓名:{{ name$ }}</span>
        <span>年龄:{{ age$ }}</span>
        <button v-stream:click="setName$">点击设置name的值</button>
    </div>
</template>

<script>
export default {
    domStreams: [
        'setName$'
    ],
    subscriptions () {
        return {
            age$: Rx.Observable.of(23)
                .map(data => data),
            name$: this.setName$
                .map(e => 'myName')
                .startWith('')
        }
    }
}
</script>

Как показано выше, Rx.Observable.of(23) будет выдавать значение 23 при подписке, а this.setName$ — это событие потока, которое определено в domStreams и на самом деле является субъектом (подробности см. RxJS для подробностей). Определение темы), когда пользователь нажимает кнопку, будут отправлены данные источника клика. Как показано в операторе карты на рисунке выше, объект события, отправленный источником данных, будет получен (здесь мы не используем этот объект, а просто возвращаем определенную строку 'myName'), startWith инициализирует значение name$ пустой строкой, где vue-rx уже сделал для нас неявную привязку подписки, поэтому значение 23 будет отправлено немедленно и, наконец, назначено возрасту $, затем привязать к представлению. Здесь мы можем рассматривать возраст $ и имя $ как результат наблюдаемого потока, испускаемого источником данных. Этот поток является чувствительным, и первоначально выданное значение будет обработано различными операторами ответа на страницу.

3. Используйте RxJS после интеграции vue-rx

гитхаб-адрес

В проекте используется конструкция участка. Примеры включают сравнение нативного использования и интеграции vue-rx, использование событий и примеры общих операторов (включая выбор сценариев использования для switchMap, concatMap, ExhaustMap и т. д.).

1. Создайте наблюдаемое

<template>
  <div>
    <h3>demo2 创建将数据转化成Observable方式</h3>
    <p>字符串:{{ str$ }}</p>
    <p>
      数组: 
      <span v-for="(num, index) in arr$" :key="index">{{ num }}</span>
    </p>
    <p>对象:{{ obj$.a }}</p>
    <p>布尔值:{{ bool$ }}</p>
    <p>promise:{{ promise$ }}</p>
    <p>interval: {{ interval$ }}</p>
  </div>
</template>

<script>
import Rx from 'rxjs/Rx'

export default {
  subscriptions () {
    return {
      /**
       * 普通数据类型都可以用of进行转换
       * promise对象可用from或者fromPromise
       * interval可在给定时间区间内发出自增数字
       */
      str$: Rx.Observable.of('str'),
      arr$: Rx.Observable.of([1, 2, 3]),
      obj$: Rx.Observable.of({ 
        a: 'test-obj' 
      }),
      bool$: Rx.Observable.of(true),
      promise$: Rx.Observable.fromPromise(this.getPromise()),
      interval$: Rx.Observable.interval(1000)
    }
  },
  methods: {
    getPromise () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('promise')
        }, 1000)
      })
    }
  }
}
</script>

После создания потока данных его использование аналогично данным, и результат потока данных может быть привязан к представлению.

2. Использование событий

// 没有集成vue-rx

export default {
  ...

  // 需要获取dom,所以必须是mounted后执行才能成功
  mounted () {
    // fromEvent可以将dom绑定事件并转化成Observable可观察对象
    Rx.Observable.fromEvent(this.$refs['btn'], 'click')
      .subscribe(e => {
        this.data = '成功获取data'
      })
  },

  ... 
}

// 集成vue-rx后
<template>
  <button class="btn" v-stream:click="getData$">点击获取数据</button>
</template>

<script>
export default {
  ...

  // v-stream事件可以统一写在这里,具体可以看vue-rx的使用
  domStreams: [
    'getData$'
  ],
  subscriptions () {
    return {
      data$: this.getData$
        // map操作符主要用于映射数据,这里我们直接返回了一个字符串
        .map(e => {
          return '成功获取data'
        })
    }
  }
}
</script>

3. Использование switchMap, concatMap, ExhaustMap

Как правило, эти операторы будут использоваться в сочетании с HTTP-запросами. Давайте рассмотрим несколько простых вариантов использования. После нажатия преобразуйте текущий поток в новый поток.

<template>
  <div>
    <h3>demo4 各种map方法运用</h3>
    <button class="btn" v-stream:click="getConcatMapCount$">点击获取concatMapCount$</button>
    <p>{{ concatMapCount$ }}</p>
    <button class="btn" v-stream:click="getSwitchMapCount$">点击获取switchMapCount$</button>
    <p>{{ switchMapCount$ }}</p>
    <button class="btn" v-stream:click="getExhaustMapCount$">点击获取exhaustMapCount$</button>
    <p>{{ exhaustMapCount$ }}</p>
  </div>
</template>

<script>
import Rx from 'rxjs/Rx'

export default {
  data () {
    return {
      count: 0
    }
  },
  domStreams: [
    'getConcatMapCount$',
    'getSwitchMapCount$',
    'getExhaustMapCount$'
  ],
  subscriptions () {
    /**
     * 下面的operator会把一个Observable转化成另外一个Observable
     * 通过返回一个观察流继续处理数据
     */
    return {
      /**
       * 当你连续点击按钮多次获取数据时,cancatMap会将获取到的数据按队列发出
       */
      concatMapCount$: this.getConcatMapCount$
        .concatMap((e) => {
          return Rx.Observable.from(this.getCount())
        }),
      /**
       * 当你连续点击按钮多次获取数据时,switchMap只会将最后一个点击发出的值发出,前面发出的值会被吞掉
       */
      switchMapCount$: this.getSwitchMapCount$
        .switchMap((e) => {
          return Rx.Observable.from(this.getCount())
        }),
      /**
       * 当你连续点击按钮多次时,exhaustMap仅执行一次,在第一次值发出后,才可以继续点击下一次发出值
       */
      exhaustMapCount$: this.getExhaustMapCount$
        .exhaustMap(e => {
          return Rx.Observable.from(this.getCount())
        })
    }
  },
  methods: {
    getCount () {
      return new Promise((resolve, reject) => {
        this.count++
        setTimeout(() => {
          resolve(this.count)
        }, 2000)
      })
    }
  }
}
</script>

Приведенный выше getCount считается ответом на HTTP-запрос через 2 секунды. При непрерывном нажатии эти операторы карты будут вести себя по-разному.

Например, concatMap будет отправлять добавочный счетчик каждые две секунды после нескольких кликов, в то время как switchMap будет отправлять только счетчик последнего клика после нескольких кликов. Например, если я нажму 3 раза, switchMapCount $ будет отправлен через 2 секунды. 3 вместо 1. ExhaustMap не будет выполнять последующие клики до тех пор, пока первый клик не будет реагировать, пока клик после ответа не будет действительным.

4. О Rx5 и Rx6

Вышеупомянутый склад является примером, написанным на основе Rx5, а новый Rx6 имеет некоторые изменения в API.Метод вызова оператора больше не является цепным вызовом, а объединяется путем передачи оператора канала и ссылки Наблюдаемый объект также был изменен, подробности см. в официальной документации.