+83
-3
lines changedFilter options
+83
-3
lines changed Original file line number Diff line number Diff line change
@@ -14,10 +14,14 @@ import {
14
14
ComponentPublicInstance,
15
15
Ref,
16
16
cloneVNode,
17
-
provide
17
+
provide,
18
+
defineAsyncComponent,
19
+
Component
18
20
} from '@vue/runtime-test'
19
21
import { KeepAliveProps } from '../../src/components/KeepAlive'
20
22
23
+
const timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))
24
+
21
25
describe('KeepAlive', () => {
22
26
let one: ComponentOptions
23
27
let two: ComponentOptions
@@ -823,4 +827,53 @@ describe('KeepAlive', () => {
823
827
await nextTick()
824
828
expect(serializeInner(root)).toBe(`<div foo>changed</div>`)
825
829
})
830
+
831
+
test('should work with async component', async () => {
832
+
let resolve: (comp: Component) => void
833
+
const AsyncComp = defineAsyncComponent(
834
+
() =>
835
+
new Promise(r => {
836
+
resolve = r as any
837
+
})
838
+
)
839
+
840
+
const toggle = ref(true)
841
+
const instanceRef = ref<any>(null)
842
+
const App = {
843
+
render: () => {
844
+
return h(
845
+
KeepAlive,
846
+
{ include: 'Foo' },
847
+
() => (toggle.value ? h(AsyncComp, { ref: instanceRef }) : null)
848
+
)
849
+
}
850
+
}
851
+
852
+
render(h(App), root)
853
+
// async component has not been resolved
854
+
expect(serializeInner(root)).toBe('<!---->')
855
+
856
+
resolve!({
857
+
name: 'Foo',
858
+
data: () => ({ count: 0 }),
859
+
render() {
860
+
return h('p', this.count)
861
+
}
862
+
})
863
+
864
+
await timeout()
865
+
// resolved
866
+
expect(serializeInner(root)).toBe('<p>0</p>')
867
+
868
+
// change state + toggle out
869
+
instanceRef.value.count++
870
+
toggle.value = false
871
+
await nextTick()
872
+
expect(serializeInner(root)).toBe('<!---->')
873
+
874
+
// toggle in, state should be maintained
875
+
toggle.value = true
876
+
await nextTick()
877
+
expect(serializeInner(root)).toBe('<p>1</p>')
878
+
})
826
879
})
Original file line number Diff line number Diff line change
@@ -13,6 +13,8 @@ import { defineComponent } from './apiDefineComponent'
13
13
import { warn } from './warning'
14
14
import { ref } from '@vue/reactivity'
15
15
import { handleError, ErrorCodes } from './errorHandling'
16
+
import { isKeepAlive } from './components/KeepAlive'
17
+
import { queueJob } from './scheduler'
16
18
17
19
export type AsyncComponentResolveResult<T = Component> = T | { default: T } // es modules
18
20
@@ -109,8 +111,14 @@ export function defineAsyncComponent<
109
111
}
110
112
111
113
return defineComponent({
112
-
__asyncLoader: load,
113
114
name: 'AsyncComponentWrapper',
115
+
116
+
__asyncLoader: load,
117
+
118
+
get __asyncResolved() {
119
+
return resolvedComp
120
+
},
121
+
114
122
setup() {
115
123
const instance = currentInstance!
116
124
@@ -174,6 +182,11 @@ export function defineAsyncComponent<
174
182
load()
175
183
.then(() => {
176
184
loaded.value = true
185
+
if (instance.parent && isKeepAlive(instance.parent.vnode)) {
186
+
// parent is keep-alive, force update so the loaded component's
187
+
// name is taken into account
188
+
queueJob(instance.parent.update)
189
+
}
177
190
})
178
191
.catch(err => {
179
192
onError(err)
Original file line number Diff line number Diff line change
@@ -189,6 +189,11 @@ export interface ComponentOptionsBase<
189
189
* @internal
190
190
*/
191
191
__asyncLoader?: () => Promise<ConcreteComponent>
192
+
/**
193
+
* the inner component resolved by the AsyncComponentWrapper
194
+
* @internal
195
+
*/
196
+
__asyncResolved?: ConcreteComponent
192
197
/**
193
198
* cache for merged $options
194
199
* @internal
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ import {
36
36
import { setTransitionHooks } from './BaseTransition'
37
37
import { ComponentRenderContext } from '../componentPublicInstance'
38
38
import { devtoolsComponentAdded } from '../devtools'
39
+
import { isAsyncWrapper } from '../apiAsyncComponent'
39
40
40
41
type MatchPattern = string | RegExp | string[] | RegExp[]
41
42
@@ -257,7 +258,15 @@ const KeepAliveImpl: ComponentOptions = {
257
258
258
259
let vnode = getInnerChild(rawVNode)
259
260
const comp = vnode.type as ConcreteComponent
260
-
const name = getComponentName(comp)
261
+
262
+
// for async components, name check should be based in its loaded
263
+
// inner component if available
264
+
const name = getComponentName(
265
+
isAsyncWrapper(vnode)
266
+
? (vnode.type as ComponentOptions).__asyncResolved || {}
267
+
: comp
268
+
)
269
+
261
270
const { include, exclude, max } = props
262
271
263
272
if (
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4