rxjs與vue

原創文章,轉載請註明出處

使用vue-rx插件將vue和rxjs聯繫起來vue

在main.js中將vue-rx注入vue中ios

import Vue from 'vue'
import App from './App'
import router from './router'
import VueRx from 'vue-rx'

// Vue.config.productionTip = false
Vue.use(VueRx)
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

例子一

使用 observableMethods 選項聲明observable,也可使用this.$createObservableMethod('muchMore')建立
調用註冊的observable方法muchMore(500),至關於nextx(500)
merge是將多個observable合併起來,統一監聽處理
scan是累計處理git

<template>
  <div>
    <div>{{ count }}</div>
    <button v-on:click="muchMore(500)">Add 500</button>
    <button v-on:click="minus(minusDelta1)">Minus on Click</button>
    <pre>{{ $data }}</pre>
  </div>
</template>

<script>
import { merge } from 'rxjs'
import { startWith, scan } from 'rxjs/operators'

// 使用 observableMethods 選項聲明observable,也可使用this.$createObservableMethod('muchMore')建立
// 調用註冊的observable方法muchMore(500),至關於nextx(500)
// merge是將多個observable合併起來,統一監聽處理
// scan是累計處理

export default {
  name: 'HelloWorld',
  data() {
    return {
      minusDelta1: -1,
      minusDelta2: -1
    }
  },
  observableMethods: {
    muchMore: 'muchMore$',
    minus: 'minus$'
  }, // equivalent of above: ['muchMore','minus']
  subscriptions() {
    return {
      count: merge(this.muchMore$, this.minus$).pipe(
        startWith(0),
        scan((total, change) => total + change)
      )
    }
  }
}
</script>

例子二

vue-rx 提供 v-stream讓你向一個 Rx Subject 流式發送 DOM 事件
渲染髮生以前你須要在vm實例上提早註冊數據,好比plus$
傳遞額外參數 傳遞參數github

<template>
  <div>
    <div>{{ count }}</div>
    <button v-stream:click="plus$">+</button>
    <button v-stream:click="minus$">-</button>
  </div>
</template>
<script>
import { merge } from 'rxjs'
import { map,startWith, scan } from 'rxjs/operators'
export default {
  domStreams: ['plus$', 'minus$'],
  subscriptions() {
    return {
      count: merge(
        this.plus$.pipe(map(() => 1)),
        this.minus$.pipe(map(() => -1))
      ).pipe(
        startWith(0),
        scan((total, change) => total + change)
      )
    }
  }
}
</script>

例子三

組件觸發父組件流事件
pluck操做符抽取特定的屬性流傳下去axios

<template>
  <div>
    <div>{{ count }}</div>
    <!-- simple usage -->
    <button v-stream:click="plus$">Add on Click</button>
    <button
      v-stream:click="{ subject: plus$, data: minusDelta1, options:{once:true} }"
    >Add on Click (Option once:true)</button>
    <!-- you can also stream to the same subject with different events/data -->
    <button
      v-stream:click="{ subject: minus$, data: minusDelta1 }"
      v-stream:mousemove="{ subject: minus$, data: minusDelta2 }"
    >Minus on Click &amp; Mousemove</button>
    <pre>{{ $data }}</pre>
    <my-button v-stream:click="plus$"></my-button>
  </div>
</template>

<script>
// import { Observable, Subject, ReplaySubject, from, of, range } from 'rxjs';
// import { map, filter, switchMap } from 'rxjs/operators';
import { merge } from 'rxjs'
import { map, pluck, startWith, scan } from 'rxjs/operators'

export default {
  data() {
    return {
      minusDelta1: -1,
      minusDelta2: -1
    }
  },
  components: {
    myButton: {
      template: `<button @click="$emit('click')">MyButton</button>`
    }
  },
  created() {
    //Speed up mousemove minus delta after 5s
    setTimeout(() => {
      this.minusDelta2 = -5
    }, 5000)
  },
  // declare dom stream Subjects
  domStreams: ['plus$', 'minus$'],
  subscriptions() {
    return {
      count: merge(
        this.plus$.pipe(map(() => 1)),
        this.minus$.pipe(pluck('data'))
      ).pipe(
        startWith(0),
        scan((total, change) => total + change)
      )
    }
  }
}
</script>

異步請求

from 從一個數組、類數組對象、Promise、迭代器對象或者類 Observable 對象建立一個 Observable
pluck 將每一個源值(對象)映射成它指定的嵌套屬性。
filter 相似於你們所熟知的 Array.prototype.filter 方法,此操做符從源 Observable 中 接收值,將值傳遞給 predicate 函數而且只發出返回 true 的這些值
debounceTime 只有在特定的一段時間通過後而且沒有發出另外一個源值,才從源 Observable 中發出一個值
distinctUntilChanged 返回 Observable,它發出源 Observable 發出的全部與前一項不相同的項數組

switchMap 將每一個源值投射成 Observable,該 Observable 會合併到輸出 Observable 中, 而且只使用最新投射的Observable中的獲取的值。app

<template>
  <div>
    <input v-model="search">
    <div v-if="results">
      <ul v-if="results.length">
        <li :key="match.title" v-for="match in results">
          <p>{{ match.title }}</p>
          <p>{{ match.description }}</p>
        </li>
      </ul>
      <p v-else>No matches found.</p>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import { from } from 'rxjs'
import {
  pluck,
  filter,
  debounceTime,
  distinctUntilChanged,
  switchMap,
  map
} from 'rxjs/operators'


let a = 1
//模仿異步返回請求數據
//a=1時,表明第一個返回,5秒以後返回
//a=2時,表明第一個返回,2秒以後返回
//(故意製造,先請求的數據後返回的場景)
function fetchTerm(term) {
  console.log(term, '--')
  let fetchdata = new Promise((resolve, reject) => {
    let i = a
    console.log('發起請求' + i)
    if (i == 1) {
      setTimeout(() => {
        console.log('獲取請求' + i)
        resolve([
          {
            description: 'description1',
            title: '第一次的請求' + term + '第' + i + '次'
          },
          {
            description: 'description2',
            title: '第一次的請求p' + term + '第' + i + '次'
          }
        ])
      }, 5000)
    } else {
      setTimeout(() => {
        console.log('獲取請求' + i)
        resolve([
          {
            description: 'description1',
            title: '第二次的請求' + term + '第' + i + '次'
          },
          {
            description: 'description2',
            title: '第二次的請求p' + term + '第' + i + '次'
          }
        ])
        a = 0
      }, 2000)
    }
  })

  a = a + 1
  console.log('ppp')
  return from(fetchdata)
}

function formatResult(res) {
  console.log(res)
  return res.map(obj => {
    return {
      title: obj.title + 'ooo',
      description: obj.description + 'ppp'
    }
  })
}

export default {
  data() {
    return {
      search: ''
    }
  },
  subscriptions() {
    return {
      // this is the example in RxJS's readme.
      results: this.$watchAsObservable('search').pipe(
        pluck('newValue'),
        map(a => {
          console.log(a)
          return a
        }),
        filter(text => text.length > 2),
        debounceTime(500),
        distinctUntilChanged(),
        switchMap(fetchTerm), //異步請求,先請求的可能後到。解決這個問題
        map(formatResult)
      )
    }
  }
}
</script>

案例下載dom

vue_rx文檔 異步

相關文章
相關標籤/搜索