Skip to content

Commit 0da8f3f

Browse files
committed
$createObservableFunction
1 parent fa85abe commit 0da8f3f

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed

example/counter-function.html

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!-- this demo requires a browser that natively supports ES2015 -->
2+
3+
<script src="https://unpkg.com/@reactivex/rxjs/dist/global/Rx.js"></script>
4+
<script src="https://unpkg.com/vue/dist/vue.js"></script>
5+
<script src="../dist/vue-rx.js"></script>
6+
7+
<div id="app">
8+
<div>{{ count }}</div>
9+
10+
<!-- simple usage -->
11+
<button v-on:click="plus(500)">Add 500</button>
12+
13+
<button v-stream:click="{ subject: plus$, data: minusDelta1, options:{once:true} }">Add on Click (Option once:true)</button>
14+
15+
<!-- you can also stream to the same subject with different events/data -->
16+
<button
17+
v-stream:click="{ subject: minus$, data: minusDelta1 }"
18+
v-stream:mousemove="{ subject: minus$, data: minusDelta2 }">
19+
Minus on Click &amp; Mousemove
20+
</button>
21+
22+
<pre>{{ $data }}</pre>
23+
24+
<my-button v-stream:click="plus$"></my-button>
25+
</div>
26+
27+
<script>
28+
new Vue({
29+
el: '#app',
30+
31+
data () {
32+
return {
33+
minusDelta1: -1,
34+
minusDelta2: -1
35+
}
36+
},
37+
38+
components: {
39+
myButton: {
40+
template: '<button>MyButton</button>'
41+
}
42+
},
43+
44+
created () {
45+
//Speed up mousemove minus delta after 5s
46+
setTimeout(() => {
47+
this.minusDelta2 = -5
48+
}, 5000);
49+
50+
},
51+
52+
// declare dom stream Subjects
53+
domStreams: ['plus$', 'minus$'],
54+
55+
methods:{
56+
},
57+
58+
subscriptions () {
59+
var count$ = Rx.Observable
60+
.merge(
61+
this.$createObservableFunction('plus'),
62+
this.plus$.map(() => 1),
63+
this.minus$.pluck('data')
64+
)
65+
.startWith(0)
66+
.scan((total, change) => total + change)
67+
68+
return {
69+
count: count$
70+
}
71+
}
72+
})
73+
</script>

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import watchAsObservable from './methods/watchAsObservable'
77
import fromDOMEvent from './methods/fromDOMEvent'
88
import subscribeTo from './methods/subscribeTo'
99
import eventToObservable from './methods/eventToObservable'
10+
import createObservableFunction from './methods/createObservableFunction'
1011

1112
export default function VueRx (Vue, Rx) {
1213
install(Vue, Rx)
@@ -16,6 +17,7 @@ export default function VueRx (Vue, Rx) {
1617
Vue.prototype.$fromDOMEvent = fromDOMEvent
1718
Vue.prototype.$subscribeTo = subscribeTo
1819
Vue.prototype.$eventToObservable = eventToObservable
20+
Vue.prototype.$createObservableFunction = createObservableFunction
1921
}
2022

2123
// auto install
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Rx, hasRx, warn } from '../util'
2+
3+
/**
4+
* @name vue.prototype.$createObservableFunction
5+
* @description Creates an observable from a given function name.
6+
* @param {String} functionName Function name
7+
* @param {Boolean} [passContext] Append the call context at the end of emit data?
8+
* @return {Observable} Hot stream
9+
*/
10+
export default function createObservableFunction (functionName, passContext) {
11+
if (!hasRx()) {
12+
return
13+
}
14+
const vm = this
15+
16+
if (!Rx.Observable.prototype.share) {
17+
warn(
18+
`No 'share' operator. ` +
19+
`$createObservableFunction returns a shared hot observable. ` +
20+
`Try import 'rxjs/add/operator/share' for creating ${functionName}`,
21+
vm
22+
)
23+
return
24+
}
25+
26+
if(vm[functionName] !== undefined){
27+
warn(
28+
'Potential bug: ' +
29+
`Method ${functionName} already defined on vm and has been overwritten by $createObservableFunction.` +
30+
String(vm[functionName]),
31+
vm
32+
)
33+
}
34+
35+
let creator = function (observer) {
36+
37+
vm[functionName] = function () {
38+
let args = Array.from(arguments);
39+
if(passContext){
40+
args.push(this);
41+
observer.next(args);
42+
}else{
43+
if (args.length <= 1) {
44+
observer.next(args[0]);
45+
} else {
46+
observer.next(args);
47+
}
48+
}
49+
};
50+
return function() {
51+
delete vm[functionName];
52+
};
53+
};
54+
55+
//Must be a hot stream otherwise function context may overwrite over and over again
56+
return Rx.Observable.create(creator).share();
57+
}

test/test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const Observable = require('rxjs/Observable').Observable
1010
const Subject = require('rxjs/Subject').Subject
1111
const Subscription = require('rxjs/Subscription').Subscription
1212
require('rxjs/add/observable/fromEvent')
13+
require('rxjs/add/operator/share')
1314

1415
// user
1516
require('rxjs/add/operator/map')
@@ -316,3 +317,36 @@ test('$eventToObservable() with lifecycle hooks', done => {
316317
vm.$destroy()
317318
})
318319
})
320+
321+
322+
test('$createObservableFunction() with no context', done => {
323+
const vm = new Vue({
324+
created () {
325+
this.$createObservableFunction('add')
326+
.subscribe(function (param) {
327+
expect(param).toEqual('hola')
328+
done(param)
329+
})
330+
}
331+
})
332+
nextTick(() => {
333+
vm.add('hola')
334+
})
335+
})
336+
337+
test('$createObservableFunction() with muli params & context', done => {
338+
const vm = new Vue({
339+
created () {
340+
this.$createObservableFunction('add',true)
341+
.subscribe(function (param) {
342+
expect(param[0]).toEqual('hola')
343+
expect(param[1]).toEqual('mundo')
344+
expect(param[2]).toEqual(vm)
345+
done(param)
346+
})
347+
}
348+
})
349+
nextTick(() => {
350+
vm.add('hola','mundo')
351+
})
352+
})

0 commit comments

Comments
 (0)