Skip to content

Commit a2a776f

Browse files
committed
fix(vue3): computed/inject from mixins/extends
vuejs/core#3566
1 parent 1fbebb8 commit a2a776f

File tree

3 files changed

+163
-11
lines changed

3 files changed

+163
-11
lines changed

packages/app-backend-vue3/src/components/data.ts

+54-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BackendContext } from '@vue-devtools/app-backend-api'
22
import { getInstanceName, getUniqueComponentId } from './util'
33
import { camelize, get, set } from '@vue-devtools/shared-utils'
44
import SharedData from '@vue-devtools/shared-utils/lib/shared-data'
5-
import { HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
5+
import { ComponentInstance, HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
66
import { returnError } from '../util'
77

88
/**
@@ -18,13 +18,14 @@ export function getInstanceDetails (instance: any, ctx: BackendContext): Inspect
1818
}
1919

2020
function getInstanceState (instance) {
21+
const mergedType = resolveMergedOptions(instance)
2122
return processProps(instance).concat(
2223
processState(instance),
2324
processSetupState(instance),
24-
processComputed(instance),
25+
processComputed(instance, mergedType),
2526
processAttrs(instance),
2627
processProvide(instance),
27-
processInject(instance),
28+
processInject(instance, mergedType),
2829
processRefs(instance)
2930
)
3031
}
@@ -173,8 +174,8 @@ function getSetupStateInfo (raw: any) {
173174
* @param {Vue} instance
174175
* @return {Array}
175176
*/
176-
function processComputed (instance) {
177-
const type = instance.type
177+
function processComputed (instance, mergedType) {
178+
const type = mergedType
178179
const computed = []
179180
const defs = type.computed || {}
180181
// use for...in here because if 'computed' is not defined
@@ -215,17 +216,17 @@ function processProvide (instance) {
215216
}))
216217
}
217218

218-
function processInject (instance) {
219-
if (!instance.type || !instance.type.inject) return []
219+
function processInject (instance, mergedType) {
220+
if (!mergedType?.inject) return []
220221
let keys = []
221-
if (Array.isArray(instance.type.inject)) {
222-
keys = instance.type.inject.map(key => ({
222+
if (Array.isArray(mergedType.inject)) {
223+
keys = mergedType.inject.map(key => ({
223224
key,
224225
originalKey: key
225226
}))
226227
} else {
227-
keys = Object.keys(instance.type.inject).map(key => {
228-
const value = instance.type.inject[key]
228+
keys = Object.keys(mergedType.inject).map(key => {
229+
const value = mergedType.inject[key]
229230
let originalKey
230231
if (typeof value === 'string') {
231232
originalKey = value
@@ -323,3 +324,45 @@ export function getCustomInstanceDetails (instance) {
323324
}
324325
}
325326
}
327+
328+
function resolveMergedOptions (
329+
instance: ComponentInstance
330+
) {
331+
const raw = instance.type
332+
const { mixins, extends: extendsOptions } = raw
333+
const globalMixins = instance.appContext.mixins
334+
if (!globalMixins.length && !mixins && !extendsOptions) return raw
335+
const options = {}
336+
globalMixins.forEach(m => mergeOptions(options, m, instance))
337+
mergeOptions(options, raw, instance)
338+
return options
339+
}
340+
341+
function mergeOptions (
342+
to: any,
343+
from: any,
344+
instance: ComponentInstance
345+
) {
346+
if (typeof from === 'function') {
347+
from = from.options
348+
}
349+
350+
const { mixins, extends: extendsOptions } = from
351+
352+
extendsOptions && mergeOptions(to, extendsOptions, instance)
353+
mixins &&
354+
mixins.forEach((m) =>
355+
mergeOptions(to, m, instance)
356+
)
357+
358+
for (const key of ['computed', 'inject']) {
359+
if (Object.prototype.hasOwnProperty.call(from, key)) {
360+
if (!to[key]) {
361+
to[key] = from[key]
362+
} else {
363+
Object.assign(to[key], from[key])
364+
}
365+
}
366+
}
367+
return to
368+
}

packages/shell-dev-vue3/src/App.vue

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Other from './Other.vue'
1414
import SetupRender from './SetupRender.js'
1515
import Form from './Form.vue'
1616
import Heavy from './Heavy.vue'
17+
import Mixins from './Mixins.vue'
1718
1819
import { h } from 'vue'
1920
@@ -36,6 +37,7 @@ export default {
3637
SetupRender,
3738
Form,
3839
Heavy,
40+
Mixins,
3941
inline: {
4042
render: () => h('h3', 'Inline component definition')
4143
}
@@ -82,6 +84,7 @@ export default {
8284
<Other />
8385
<SetupRender />
8486
<Form />
87+
<Mixins />
8588
<inline />
8689
<global />
8790

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<script>
2+
export default {
3+
extends: {
4+
extends: {
5+
data () {
6+
return {
7+
dataFromExtendsExtends: 'hey'
8+
}
9+
},
10+
11+
computed: {
12+
computedFromExtendsExtends () {
13+
return 'extends extends:' + this.dataFromMixinExtends
14+
}
15+
},
16+
17+
inject: {
18+
meow: {
19+
from: 'cat',
20+
default: 'Meow'
21+
}
22+
}
23+
},
24+
25+
mixins: [
26+
{
27+
data () {
28+
return {
29+
dataFromExtendsMixin: 'cat'
30+
}
31+
},
32+
33+
computed: {
34+
computedFromExtendsMixin () {
35+
return 'extends mixin:' + this.dataFromMixinMixin
36+
}
37+
}
38+
}
39+
],
40+
41+
data () {
42+
return {
43+
dataFromExtends: 'meow'
44+
}
45+
},
46+
47+
computed: {
48+
computedFromExtends () {
49+
return 'extends:' + this.dataFromExtends
50+
}
51+
}
52+
},
53+
mixins: [
54+
{
55+
extends: {
56+
data () {
57+
return {
58+
dataFromMixinExtends: 'cheese'
59+
}
60+
},
61+
62+
computed: {
63+
computedFromMixinExtends () {
64+
return 'mixin extends:' + this.dataFromMixinExtends
65+
}
66+
}
67+
},
68+
69+
mixins: [
70+
{
71+
data () {
72+
return {
73+
dataFromMixinMixin: 'waf'
74+
}
75+
},
76+
77+
computed: {
78+
computedFromMixinMixin () {
79+
return 'mixin mixin:' + this.dataFromMixinMixin
80+
}
81+
}
82+
}
83+
],
84+
85+
data () {
86+
return {
87+
dataFromMixin: '42'
88+
}
89+
},
90+
91+
computed: {
92+
computedFromMixin () {
93+
return 'mixin:' + this.dataFromMixin
94+
}
95+
}
96+
}
97+
]
98+
}
99+
</script>
100+
101+
<template>
102+
<input v-model="dataFromExtends">
103+
{{ computedFromExtends }}
104+
<input v-model="dataFromMixin">
105+
{{ computedFromMixin }}
106+
</template>

0 commit comments

Comments
 (0)