Skip to content

Commit 6f92782

Browse files
committed
add feature eventToObservable
1 parent e8bdc2d commit 6f92782

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,30 @@ vm.$watchAsObservable('a')
183183

184184
The optional `options` object accepts the same options as `vm.$watch`.
185185

186+
#### `$eventToObservable(event)`
187+
188+
> This feature requires RxJS.
189+
190+
Convert vue.$on (including lifecycle events) to Observables. The emitted value is in the format of `{ name, msg }`:
191+
192+
``` js
193+
var vm = new Vue({
194+
created () {
195+
this.$eventToObservable('customEvent')
196+
.subscribe((event) => console.log(event.name,event.msg))
197+
}
198+
})
199+
200+
// vm.$once vue-rx version
201+
this.$eventToObservable('customEvent')
202+
.take(1)
203+
204+
// Another way to auto unsub:
205+
let beforeDestroy$ = this.$eventToObservable('hook:beforeDestroy')
206+
this.$eventToObservable('customEvent')
207+
.takeUntil(beforeDestroy$)
208+
```
209+
186210
#### `$subscribeTo(observable, next, error, complete)`
187211

188212
This is a prototype method added to instances. You can use it to subscribe to an observable, but let VueRx manage the dispose/unsubscribe.

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import streamDirective from './directives/stream'
44
import watchAsObservable from './methods/watchAsObservable'
55
import fromDOMEvent from './methods/fromDOMEvent'
66
import subscribeTo from './methods/subscribeTo'
7+
import eventToObservable from './methods/eventToObservable'
78

89
export default function VueRx (Vue, Rx) {
910
install(Vue, Rx)
@@ -12,6 +13,7 @@ export default function VueRx (Vue, Rx) {
1213
Vue.prototype.$watchAsObservable = watchAsObservable
1314
Vue.prototype.$fromDOMEvent = fromDOMEvent
1415
Vue.prototype.$subscribeTo = subscribeTo
16+
Vue.prototype.$eventToObservable = eventToObservable
1517
}
1618

1719
// auto install

src/methods/eventToObservable.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Rx, hasRx } from '../util'
2+
3+
/**
4+
* @see {@link https://vuejs.org/v2/api/#vm-on}
5+
* @param {String||Array} evtName Event name
6+
* @return {Observable} Event stream
7+
*/
8+
export default function eventToObservable (evtName) {
9+
if (!hasRx()) {
10+
return
11+
}
12+
const vm = this
13+
let evtNames = Array.isArray(evtName) ? evtName : [evtName]
14+
const obs$ = Rx.Observable.create(observer => {
15+
let eventPairs = evtNames.map(name =>{
16+
let callback = msg => observer.next({name, msg})
17+
vm.$on(name, callback)
18+
return {name, callback}
19+
})
20+
return () => {
21+
//Only remove the specific callback
22+
eventPairs.forEach(pair => vm.$off(pair.name, pair.callback))
23+
}
24+
})
25+
26+
;(vm._obSubscriptions || (vm._obSubscriptions = [])).push(obs$)
27+
return obs$
28+
}

test/test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,43 @@ test('$subscribeTo()', () => {
284284
next(2)
285285
expect(results).toEqual([1]) // should not trigger anymore
286286
})
287+
288+
289+
test('$eventToObservable()', done => {
290+
let calls = 0;
291+
const vm = new Vue({
292+
created(){
293+
let ob = this.$eventToObservable('ping')
294+
.subscribe(function (event) {
295+
expect(event.name).toEqual('ping');
296+
expect(event.msg).toEqual('ping message');
297+
calls++
298+
});
299+
}
300+
});
301+
vm.$emit('ping','ping message');
302+
303+
nextTick(()=>{
304+
vm.$destroy();
305+
//Should not emit
306+
vm.$emit('pong','pong message');
307+
expect(calls).toEqual(1);
308+
done()
309+
});
310+
});
311+
312+
313+
test('$eventToObservable() with lifecycle hooks', done => {
314+
const vm = new Vue({
315+
created(){
316+
this.$eventToObservable('hook:beforeDestroy')
317+
.subscribe(function (event) {
318+
console.log(event);
319+
done(event)
320+
});
321+
}
322+
});
323+
nextTick(()=>{
324+
vm.$destroy()
325+
})
326+
});

0 commit comments

Comments
 (0)