zoukankan      html  css  js  c++  java
  • rxjs与vue

    原创文章,转载请注明出处

    使用vue-rx插件将vue和rxjs联系起来

    在main.js中将vue-rx注入vue中

    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是累计处理

    <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( 传递额外参数<button v-stream:click="{ subject: plus), data: someData }">+ 传递参数

    <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操作符抽取特定的属性流传下去

    <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中的获取的值。

    <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>
    
    

    案例下载

    vue_rx文档

  • 相关阅读:
    安装64位Oracle 10g超详细教程
    Linux同平台Oracle数据库整体物理迁移
    Oracle 删除重复数据只留一条
    linux下通过脚本实现自动重启程序的方法
    Linux查看系统开机时间
    Linux下oracle数据库启动和关闭操作
    curl: (6) Couldn’t resolve host ‘www.ttlsa.com’
    linux 怎么查找oracle11g的安装目录
    Linux系统管理员:不要害怕升级内核
    The Binder Architecture
  • 原文地址:https://www.cnblogs.com/panfengde/p/10144270.html
Copyright © 2011-2022 走看看