Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 90336e9

Browse filesBrowse files
committed
feat: support async setup (fix #463)
1 parent 3d9e1f2 commit 90336e9
Copy full SHA for 90336e9

File tree

Expand file treeCollapse file tree

4 files changed

+74
-6
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+74
-6
lines changed

‎src/helpers.ts

Copy file name to clipboardExpand all lines: src/helpers.ts
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ComponentOptions, ShallowUnwrapRef, Ref } from 'vue'
22

3-
import { Vue, VueConstructor, VueMixin } from './vue'
3+
import { Vue, VueBase, VueConstructor, VueMixin } from './vue'
44

55
export function Options<V extends Vue>(
66
options: ComponentOptions & ThisType<V>
@@ -80,10 +80,12 @@ export type UnwrapSetupValue<T> = T extends Ref<infer R>
8080
? R
8181
: ShallowUnwrapRef<T>
8282

83-
export function setup<R>(setupFn: () => R): UnwrapSetupValue<R> {
83+
export type UnwrapPromise<T> = T extends Promise<infer R> ? R : T
84+
85+
export function setup<R>(setupFn: () => R): UnwrapSetupValue<UnwrapPromise<R>> {
8486
// Hack to delay the invocation of setup function.
8587
// Will be called after dealing with class properties.
8688
return {
8789
__s: setupFn,
88-
} as UnwrapSetupValue<R>
90+
} as UnwrapSetupValue<UnwrapPromise<R>>
8991
}

‎src/index.ts

Copy file name to clipboardExpand all lines: src/index.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ export {
3838
UnionToIntersection,
3939
ExtractInstance,
4040
UnwrapSetupValue,
41+
UnwrapPromise,
4142
} from './helpers'

‎src/vue.ts

Copy file name to clipboardExpand all lines: src/vue.ts
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ class VueImpl {
243243
const dataKeys = Object.keys(data)
244244

245245
const plainData: any = {}
246+
let promise: Promise<any> | null = null
246247

247248
// Initialize reactive data and convert constructor `this` to a proxy
248249
dataKeys.forEach((key) => {
@@ -260,11 +261,23 @@ class VueImpl {
260261
dataKeys.forEach((key) => {
261262
if (data[key] && data[key].__s) {
262263
const setupState = data[key].__s()
263-
plainData[key] = proxyRefs(setupState)
264+
if (setupState instanceof Promise) {
265+
if (!promise) {
266+
promise = Promise.resolve(plainData)
267+
}
268+
promise = promise.then(() => {
269+
return setupState.then((value) => {
270+
plainData[key] = proxyRefs(value)
271+
return plainData
272+
})
273+
})
274+
} else {
275+
plainData[key] = proxyRefs(setupState)
276+
}
264277
}
265278
})
266279

267-
return plainData
280+
return promise ?? plainData
268281
}
269282

270283
const decorators =

‎test/specs/test.spec.ts

Copy file name to clipboardExpand all lines: test/specs/test.spec.ts
+53-1Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import 'reflect-metadata'
2-
import { h, resolveComponent, ref, onMounted, Ref, watch, toRef } from 'vue'
2+
import {
3+
h,
4+
resolveComponent,
5+
ref,
6+
onMounted,
7+
Ref,
8+
watch,
9+
toRef,
10+
nextTick,
11+
Suspense,
12+
} from 'vue'
313
import { Options, createDecorator, mixins, Vue, setup, prop } from '../../src'
414
import { mount, unmount } from '../helpers'
515

@@ -416,6 +426,48 @@ describe('vue-class-component', () => {
416426
expect(root.answer.nested.answer.value).toBe(42)
417427
})
418428

429+
it('setup: suspense', () => {
430+
const deps: Promise<any>[] = []
431+
432+
class Child extends Vue {
433+
foo = 'Hello'
434+
435+
bar = setup(() => {
436+
const a = ref(42)
437+
return {
438+
a,
439+
}
440+
})
441+
442+
baz = setup(() => {
443+
const b = ref(true)
444+
const p = Promise.resolve({
445+
b,
446+
})
447+
deps.push(p.then(() => Promise.resolve()))
448+
return p
449+
})
450+
451+
render() {
452+
return h('div', [[this.foo, this.bar.a, this.baz.b].join(',')])
453+
}
454+
}
455+
456+
class App extends Vue {
457+
render() {
458+
return h(Suspense, null, {
459+
default: h(Child),
460+
fallback: h('div', 'fallback'),
461+
})
462+
}
463+
}
464+
465+
const { root } = mount(App)
466+
return Promise.all(deps)
467+
.then(() => nextTick())
468+
.then(() => expect(root.$el.textContent).toBe('Hello,42,true'))
469+
})
470+
419471
it('reactive class properties in a composition function', (done) => {
420472
function test(message: Ref<string>) {
421473
watch(message, () => {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.