Vue.jsにRxJSを入れて、色々試してみたよ

新見晃平

@gupuru

  • Vue.jsにRxをいれると、どうなるの?
  • なにができるようになるの?
  • そもそも、Rx動くの?


Vue.js ✕ Rxを思いついた時、こう思いました!

vue rxで検索すると...

https://github.com/vuejs/vue-rx

vue-rx、色々試してみました!

RxJSの説明は、省略しています。

 

https://chibi-developer.booth.pm/items/659290

知り合いがRxJSについて本にまとめているので、「RxJSって何?」という人は
先にこちら↓を読んでおくと良い思います!

導入

npm install vue vue-rx rxjs --save
import Vue from 'vue'
import Rx from 'rxjs/Rx'
import VueRx from 'vue-rx'

Vue.use(VueRx, Rx)

基本

<template>
 <div id="app">
    <p>
      🐶: {{ count }}匹
    </p>
 </div>
</template>

<script>
  import { Observable } from 'rxjs/Observable';
  import 'rxjs/add/observable/interval';
  import 'rxjs/add/operator/filter';

  export default {
    name: 'app',
    data () {
      return {
        count: 0
      }
    },
    created () {
      Observable
        .interval(1000)
        .filter((value) => value % 2 === 0)
        .subscribe((value) => this.count = value)
    },
  }
</script>

subscriptionsを使ってみる その1

<template>
  <div id="app">
    <p>
      🐶: {{ count }}匹
    </p>
  </div>
</template>

<script>
  import { Observable } from 'rxjs/Observable';
  import 'rxjs/add/observable/interval';
  import 'rxjs/add/operator/filter';

  export default {
    name: 'app',
    subscriptions () {
      return {
        count: Observable.interval(1000)
      }
    },
  }
</script>
<template>
 <div id="app">
    <p>
      🐶: {{ count }}匹
    </p>
  </div>
</template>

<script>
  import { Observable } from 'rxjs/Observable';
  import 'rxjs/add/observable/interval';
  import 'rxjs/add/operator/filter';

  export default {
    name: 'app',
    subscriptions () {
      return {
        count: Observable.interval(1000)
          .filter((value) => value % 2 === 0)
      }
    },
  }
</script>

subscriptionsを使ってみる その2

DOM イベント その1

<template>
  <div id="app">
    <div>
      🐶: {{ count }}匹
    </div>
    <button v-stream:click="plus$">ふやす</button>
  </div>
</template>

<script>
  import { Observable } from 'rxjs/Observable';

  export default {
    name: 'app',
    domStreams: ['plus$'],
    subscriptions () {
      return {
       count: this.plus$.map(() => 1)
        .startWith(0)
        .scan((total, change) => total + change)
      }
    },
  }
</script>

DOM イベント その2-1

<template>
  <div id="app">
    <div>
      🐶: {{ count }}匹
    </div>

    <button v-stream:click="plus$">ふえるよん</button>

    <button
      v-stream:click="{ subject: minus$, data: fewMinus }"
      v-stream:mousemove="{ subject: minus$, data: ManyMinus }">
      へるよん
    </button>
  </div>
</template>

※次のスライドに続く

<script>
  import { Observable } from 'rxjs/Observable';

  export default {
    name: 'app',
    data () {
      return {
        fewMinus: -1,
        ManyMinus: -100
      }
    },
    domStreams: ['plus$', 'minus$'],
    subscriptions () {
      return {
       count: Observable.merge(
         this.plus$.map(() => 1),
         this.minus$.pluck('data')
       )
       .startWith(0)
       .scan((total, change) => total + change)
      }
    },
  }

</script>

DOM イベント その2-2

DOMイベントからObservableを作成

DOMが実際にレンダリングされる前であってもsubscriptions関数内で使用できるみたいです。(訳間違えていたら、ごめん)

<template>
  <div id="app">
    <input/>
    <p>うったやつ: {{ inputValue }}</p>
  </div>
</template>

<script>
  export default {
    name: 'app',
    subscriptions () {
      return {
        inputValue: this.$fromDOMEvent('input', 'keyup').pluck('target', 'value')
      }
    },
  }
</script>

watcher系

<template>
  <div id="app">
    <p>
      カルビ {{ count }} 枚
    </p>
    <p>
      塩タン {{ countPlus }} 枚
    </p>
    <button v-on:click="count++">追加</button>
  </div>
</template>
<script>
  export default {
    name: 'app',
    data () {
      return {
        count: 0,
      }
    },
    subscriptions () {
      return {
        countPlus: this.$watchAsObservable('count')
            .pluck('newValue')
            .startWith(this.count)
            .map(count => count + 1)
      }
    },
  }
</script>

関数呼び出し系 その1

<template>
  <div id="app">
    <p>
      壺漬けカルビ {{ count }} つ
    </p>
    <button v-on:click="add(plus)">追加</button>
    <button v-on:click="remove(minus)">やっぱやめる</button>
  </div>
</template>

※次のスライドに続く

関数呼び出し系 その2

<script>
  import { Observable } from 'rxjs/Observable';

  export default {
    name: 'app',
    data () {
      return {
        plus: 1,
        minus: -1,
      }
    },
    observableMethods: {
      add: 'add$',
      remove: 'remove$',
    },
    subscriptions () {
      return {
        count: Observable
          .merge(
            this.add$,
            this.remove$
          )
          .startWith(0)
          .scan((total, change) => total + change)
      }
    },
  }
</script>

まとめ

RxJS(vue-rx)を入れると便利になるよ!

でも...同じようなことはRxを使わなくてもできる

無理に入れる必要はないと思いました(`・ω・´)

ご清聴ありがとうございました!

Vue.jsにRxJSを入れて、色々試してみたよ

By kohei niimi

Vue.jsにRxJSを入れて、色々試してみたよ

こちらのイベントのLT資料https://cdg.connpass.com/event/68191/

  • 3,491