-
Notifications
You must be signed in to change notification settings - Fork 66
Closed
Description
I expected the computed getter to only fire when the getter is accessed. Do you think it's implementable as an option? { lazy: true }
I was able to implement the behaviour, but had to change a lot:
const prefix = 'async_computed$'
const AsyncComputed = {
install (Vue, options) {
options = options || {}
Vue.config
.optionMergeStrategies
.asyncComputed = Vue.config.optionMergeStrategies.computed
Vue.mixin({
data () {
if (this.$options.asyncComputed) {
return {
async_computed$: {}
}
}
return {}
},
beforeCreate () {
if (!this.$options.asyncComputed) {
return
}
const optionComputed = this.$options.computed
if (!this.$options.computed) this.$options.computed = {}
const computed = (
(typeof optionComputed === 'function')
? optionComputed.call(this)
: optionComputed
) || {}
// Add computed getter for each key
Object.keys(this.$options.asyncComputed || {}).forEach(key => {
computed[key] = function () {
if (typeof this.$options.asyncComputed[key] !== 'function') {
return this.$options.asyncComputed[key]
}
if (!this['_request$' + prefix + key]) {
this['_request$' + prefix + key] = true
// Call computed property
this.$options.asyncComputed[key]()
.then(value => {
// This will trigger watchers of the computed property
// because a default value was set in $data
this[prefix][key] = value
// Hacky way of allowing to trigger again
// Should use throttle-like function instead
setTimeout(() => {
this['_request$' + prefix + key] = true
}, 25)
})
.catch(err => {
// Error handler
const handler = (options.errorHandler === undefined)
? console.error.bind(console, 'Error evaluating async computed property:')
: options.errorHandler
if (options.useRawError) {
handler(err)
} else {
handler(err.stack)
}
})
}
// Return computed value
return this[prefix][key]
}
})
this.$options.computed = computed
},
created () {
if (this.$options.asyncComputed) {
// Set default value
Object.keys(this.$options.asyncComputed || {}).forEach(key => {
const fn = this.$options.asyncComputed[key], def = typeof fn.default === 'undefined' ? null : fn.default
this.$set(this[prefix], key, typeof def === 'function' ? def.call(this) : def)
})
}
}
})
}
}
export default AsyncComputed
// Auto install in dist mode
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(AsyncComputed)
}Metadata
Metadata
Assignees
Labels
No labels