Eager Vue computed property - use for cheap computed properties that always update but that don't trigger updates when their value doesn't change
export function useEagerComputed() { | |
const properties = [] | |
function eagerComputed(definitions) { | |
const computedProps = {} | |
for (const key in definitions) { | |
const effect = definitions[key] | |
properties.push({ key, effect }) | |
computedProps[key] = function () { | |
return this.$data[key] | |
} | |
} | |
return computedProps | |
} | |
const mixin = { | |
data() { | |
const data = {} | |
for (const prop of properties) { | |
data[prop.key] = undefined | |
} | |
return data | |
}, | |
created() { | |
for (const prop of properties) { | |
this.$watch(prop.effect.bind(this), (value) => { | |
this.$data[prop.key] = value | |
}) | |
} | |
} | |
} | |
return { | |
mixin, | |
eagerComputed | |
} | |
} | |
// Usage in component: | |
const { mixin, eagerComputed } = useEagerComputed() | |
export default { | |
name: 'HelloWorld', | |
mixins: [mixin], | |
data() { | |
return { | |
loadingId: 0, | |
id: 0 | |
} | |
}, | |
methods: { | |
update() { | |
this.loadingId = (this.loadingId + 1) % 3 | |
} | |
}, | |
computed: { | |
...eagerComputed({ | |
isLoading() { | |
return this.loadingId === this.id | |
} | |
}), | |
myObj() { | |
console.log('computation') | |
return { | |
isLoading: this.isLoading | |
} | |
} | |
} | |
} |
export function eagerComputedMixin<T = any> (key: string, effect: () => T) { | |
return { | |
data () { | |
return { | |
[key]: undefined, | |
} | |
}, | |
created () { | |
this.$watch(effect.bind(this), (value) => { | |
this.$data[key] = value | |
}) | |
}, | |
} | |
} |
import { watchEffect, readonly } from '@vue/composition-api' | |
export function eagerComputed<T = any> (effect: () => T) { | |
const holder = ref<T>() | |
watchEffect(() => { | |
holder.value = effect() | |
}) | |
return readonly(holder) | |
} |
import { watchEffect, readonly } from 'vue' | |
export function eagerComputed<T = any> (effect: () => T) { | |
const holder = ref<T>() | |
watchEffect(() => { | |
holder.value = effect() | |
}) | |
return readonly(holder) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Example with Vue 2: https://codesandbox.io/s/vue-eager-computed-vue2-f7eud?file=/src/components/HelloWorld.vue:147-697