vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

Home Page:https://vuejs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mixins are not merged correctly for built-in options in `this.$options`

Justineo opened this issue · comments

Version

3.0.11

Reproduction link

SFC Playground

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 #2119?

@HcySunYang Yeah I believe both issues rely on options being merged correctly.

@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.

Will take a look tomorrow

It seems it doesn't work well for extends though

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.