Skip to content

Commit 2998431

Browse files
author
Guillaume Chau
committed
feat: $autorun in computed props
1 parent 6f6a143 commit 2998431

File tree

2 files changed

+85
-48
lines changed

2 files changed

+85
-48
lines changed

src/components/MeteorSub.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default {
3434
updateSub () {
3535
if (this.$_unsub) this.$_unsub()
3636
const parameters = typeof this.parameters === 'function' ? this.parameters : () => this.parameters || []
37-
this.$_unsub = this.$addReactiveSub(this.name, parameters)
37+
this.$_unsub = this.$subscribe(this.name, parameters)
3838
},
3939
},
4040

src/index.js

Lines changed: 84 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ export default {
5050
}, merge(toData, fromData))
5151
}
5252

53+
function getResult (result) {
54+
if (result && typeof result.fetch === 'function') {
55+
result = result.fetch()
56+
}
57+
if (Vue.config.meteor.freeze) {
58+
result = Object.freeze(result)
59+
}
60+
return result
61+
}
62+
5363
function prepare () {
5464
this._trackerHandles = []
5565
this._subsAutorun = {}
@@ -75,24 +85,16 @@ export default {
7585

7686
if (!isServer || ssr) {
7787
// Subscriptions
78-
if (meteor.subscribe || meteor.$subscribe) {
79-
const subscribeOptions = Object.assign({}, meteor.subscribe, meteor.$subscribe)
80-
for (let key in subscribeOptions) {
81-
this.$addReactiveSub(key, subscribeOptions[key])
88+
if (meteor.$subscribe) {
89+
for (let key in meteor.$subscribe) {
90+
this.$subscribe(key, meteor.$subscribe[key])
8291
}
8392
}
8493

85-
const data = Object.assign({}, omit(meteor, [
86-
'subscribe',
87-
'data',
88-
]), meteor.data)
89-
9094
// Reactive data
91-
if (data) {
92-
for (let key in data) {
93-
if (key.charAt(0) !== '$') {
94-
this.$addMeteorData(key, data[key])
95-
}
95+
for (let key in meteor) {
96+
if (key.charAt(0) !== '$') {
97+
this.$addMeteorData(key, meteor[key])
9698
}
9799
}
98100
}
@@ -121,14 +123,22 @@ export default {
121123
if (this.$options.meteor && !this.$options.meteor.$lazy) {
122124
launch.call(this)
123125
}
126+
127+
// Computed props
128+
const computed = this._computedWatchers
129+
if (computed) {
130+
for (let key in computed) {
131+
this.$addComputed(key, computed[key])
132+
}
133+
}
124134
},
125135

126136
destroyed: function () {
127137
this.$stopMeteor()
128138
},
129139

130140
methods: {
131-
$subscribe (...args) {
141+
$_subscribe (...args) {
132142
if (args.length > 0) {
133143
const key = args[0]
134144
const oldSub = this._subs[key]
@@ -160,6 +170,32 @@ export default {
160170
}
161171
},
162172

173+
$subscribe (key, options) {
174+
let handle, unwatch
175+
let subscribe = params => {
176+
handle = this.$_subscribe(key, ...params)
177+
}
178+
179+
if (typeof options === 'function') {
180+
if (isServer) {
181+
subscribe(options.bind(this)())
182+
} else {
183+
unwatch = this.$watch(options, params => {
184+
subscribe(params)
185+
}, {
186+
immediate: true,
187+
})
188+
}
189+
} else {
190+
subscribe(options)
191+
}
192+
193+
return () => {
194+
if (unwatch) unwatch()
195+
if (handle) this.$stopHandle(handle)
196+
}
197+
},
198+
163199
$autorun (reactiveFunction) {
164200
let handle = Tracker.autorun(reactiveFunction)
165201
this._trackerHandles.push(handle)
@@ -193,32 +229,6 @@ export default {
193229
this._meteorActive = false
194230
},
195231

196-
$addReactiveSub (key, options) {
197-
let handle, unwatch
198-
let subscribe = params => {
199-
handle = this.$subscribe(key, ...params)
200-
}
201-
202-
if (typeof options === 'function') {
203-
if (isServer) {
204-
subscribe(options.bind(this)())
205-
} else {
206-
unwatch = this.$watch(options, params => {
207-
subscribe(params)
208-
}, {
209-
immediate: true,
210-
})
211-
}
212-
} else {
213-
subscribe(options)
214-
}
215-
216-
return () => {
217-
if (unwatch) unwatch()
218-
if (handle) this.$stopHandle(handle)
219-
}
220-
},
221-
222232
$addMeteorData (key, func) {
223233
if (typeof func === 'function') {
224234
func = func.bind(this)
@@ -238,12 +248,7 @@ export default {
238248

239249
// Function run
240250
const setResult = result => {
241-
if (result && typeof result.fetch === 'function') {
242-
result = result.fetch()
243-
}
244-
if (Vue.config.meteor.freeze) {
245-
result = Object.freeze(result)
246-
}
251+
result = getResult(result)
247252
set(this.$data.$meteor.data, key, result)
248253
}
249254

@@ -270,6 +275,38 @@ export default {
270275
unautorun()
271276
}
272277
},
278+
279+
$addComputed (key, watcher) {
280+
let computation, autorunMethod
281+
const autorun = (cb) => {
282+
if (!computation) {
283+
// Update from Meteor
284+
let dirty = false
285+
computation = autorunMethod(computation => {
286+
dirty = true
287+
watcher.value = getResult(cb.call(this))
288+
watcher.deps.forEach(dep => dep.notify())
289+
dirty = false
290+
})
291+
// Update from Vue (override)
292+
watcher.update = () => {
293+
if (!dirty) {
294+
computation.invalidate()
295+
}
296+
}
297+
}
298+
return watcher.value
299+
}
300+
// Override getter to expose $autorun
301+
const func = watcher.getter
302+
watcher.getter = () => {
303+
autorunMethod = this.$autorun
304+
this.$autorun = autorun
305+
const result = func.call(this, this)
306+
this.$autorun = autorunMethod
307+
return result
308+
}
309+
},
273310
},
274311
})
275312

0 commit comments

Comments
 (0)