Mixins are not merged correctly for built-in options in `this.$options`
Version
3.0.11
Reproduction link
Steps to reproduce
Define a component with options API:
{
mixins: [
{ computed: { bar: () => 2 } }
],
computed: {
foo: () => 1
}
}
What is expected?
this.$options.computed
should contain both foo
and bar
as keys:
this.$options.computed // { foo: () => 1, bar: () => 2 }
What is actually happening?
this.$options.computed // { foo: () => 1 }
It seems to affect all built-in options: https://github.com/vuejs/vue-next/blob/870f2a7ba35245fd8c008d2ff666ea130a7e4704/packages/runtime-core/src/componentOptions.ts#L973
This also makes Devtools unable to show data
/computed
/... defined in mixins as it relies on this.$options
.
It seems like Vue 2 does add them to $options
https://jsfiddle.net/posva/p2gz45j8/
Yeah I've checked it's how devtools currently manage to categorize properties into data
, computed
, etc.
@posva Is this issue the same as the one described by https://github.com/vuejs/vue-next/issues/2119?
@HcySunYang I think it's a bit different.
#2119 was initially about being able to retrieve beforeRouteEnter()
and other custom options added by the router when the user adds them through mixins
. Because they are custom, we would also need a custom merge strategy.
So, IMO solving this issue doesn't require solving the other one and this one is more about consistency with Vue 2 while the other one is about a missing feature given the new behavior and also about devtools. So we should prioritize this one over the other one
Currently devtools for Vue 3 only handles computed/inject keys on the component's base definition, so even if we expose $options
like in Vue 2 it still doesn't work.
It's trivial for devtools to account for mixins though, we just need to do a merge on the devtools side for computed/provide/inject here /cc @Akryum
I don't think app code should rely on core merge behavior for $options
, and the trade-off isn't worth it considering the extra amount of code needed. The behavior consistency is covered in the migration build, but in proper Vue 3 users should only use $options
for custom options, not core options.
Yeah currently resolveMergedOptions
intentionally does not account for built-in options like computed
because it's somewhat wasteful (one of the perf bottlenecks in v2).
What I'm suggesting is for devtools to also check mixins
and extends
when resolving computed/provide/inject state for an instance.