Browse Source

feat: resolve ES module default when resolving async components

dev
Evan You 8 years ago
parent
commit
0cd6ef321b
  1. 3
      src/core/vdom/helpers/resolve-async-component.js
  2. 3
      src/server/render.js
  3. 102
      test/ssr/ssr-string.spec.js
  4. 27
      test/unit/features/component/component-async.spec.js

3
src/core/vdom/helpers/resolve-async-component.js

@ -12,6 +12,9 @@ import {
import { createEmptyVNode } from 'core/vdom/vnode'
function ensureCtor (comp, base) {
if (comp.__esModule && comp.default) {
comp = comp.default
}
return isObject(comp)
? base.extend(comp)
: comp

3
src/server/render.js

@ -172,6 +172,9 @@ function renderAsyncComponent (node, isRoot, context) {
const factory = node.asyncFactory
const resolve = comp => {
if (comp.__esModule && comp.default) {
comp = comp.default
}
const { data, children, tag } = node.asyncMeta
const nodeContext = node.asyncMeta.context
const resolvedNode: any = createComponent(

102
test/ssr/ssr-string.spec.js

@ -473,7 +473,7 @@ describe('SSR: renderToString', () => {
})
})
it('renders asynchronous component', done => {
it('renders async component', done => {
renderVmWithOptions({
template: `
<div>
@ -482,11 +482,11 @@ describe('SSR: renderToString', () => {
`,
components: {
testAsync (resolve) {
resolve({
setTimeout(() => resolve({
render () {
return this.$createElement('span', { class: ['b'] }, 'testAsync')
}
})
}), 1)
}
}
}, result => {
@ -495,55 +495,58 @@ describe('SSR: renderToString', () => {
})
})
it('renders asynchronous component (hoc)', done => {
it('renders async component (Promise, nested)', done => {
const Foo = () => Promise.resolve({
render: h => h('div', [h('span', 'foo'), h(Bar)])
})
const Bar = () => ({
component: Promise.resolve({
render: h => h('span', 'bar')
})
})
renderVmWithOptions({
template: '<test-async></test-async>',
components: {
testAsync (resolve) {
resolve({
render () {
return this.$createElement('span', { class: ['b'] }, 'testAsync')
}
})
}
render: h => h(Foo)
}, res => {
expect(res).toContain(`<div data-server-rendered="true"><span>foo</span><span>bar</span></div>`)
done()
})
})
it('renders async component (ES module)', done => {
const Foo = () => Promise.resolve({
__esModule: true,
default: {
render: h => h('div', [h('span', 'foo'), h(Bar)])
}
}, result => {
expect(result).toContain('<span data-server-rendered="true" class="b">testAsync</span>')
})
const Bar = () => ({
component: Promise.resolve({
__esModule: true,
default: {
render: h => h('span', 'bar')
}
})
})
renderVmWithOptions({
render: h => h(Foo)
}, res => {
expect(res).toContain(`<div data-server-rendered="true"><span>foo</span><span>bar</span></div>`)
done()
})
})
it('renders nested asynchronous component', done => {
it('renders async component (hoc)', done => {
renderVmWithOptions({
template: `
<div>
<test-async></test-async>
</div>
`,
template: '<test-async></test-async>',
components: {
testAsync (resolve) {
const options = {
template: `
<span class="b">
<test-sub-async></test-sub-async>
</span>
`
}
options.components = {
testSubAsync (resolve) {
resolve({
render () {
return this.$createElement('div', { class: ['c'] }, 'testSubAsync')
}
})
}
testAsync: () => Promise.resolve({
render () {
return this.$createElement('span', { class: ['b'] }, 'testAsync')
}
resolve(options)
}
})
}
}, result => {
expect(result).toContain('<div data-server-rendered="true"><span class="b"><div class="c">testSubAsync</div></span></div>')
expect(result).toContain('<span data-server-rendered="true" class="b">testAsync</span>')
done()
})
})
@ -877,23 +880,6 @@ describe('SSR: renderToString', () => {
done()
})
})
it('render async components', done => {
const Foo = () => Promise.resolve({
render: h => h('div', [h('span', 'foo'), h(Bar)])
})
const Bar = () => ({
component: Promise.resolve({
render: h => h('span', 'bar')
})
})
renderVmWithOptions({
render: h => h(Foo)
}, res => {
expect(res).toContain(`<div data-server-rendered="true"><span>foo</span><span>bar</span></div>`)
done()
})
})
})
function renderVmWithOptions (options, cb) {

27
test/unit/features/component/component-async.spec.js

@ -26,6 +26,33 @@ describe('Component async', () => {
}
})
it('resolve ES module default', done => {
const vm = new Vue({
template: '<div><test></test></div>',
components: {
test: (resolve) => {
setTimeout(() => {
resolve({
__esModule: true,
default: {
template: '<div>hi</div>'
}
})
// wait for parent update
Vue.nextTick(next)
}, 0)
}
}
}).$mount()
expect(vm.$el.innerHTML).toBe('<!---->')
expect(vm.$children.length).toBe(0)
function next () {
expect(vm.$el.innerHTML).toBe('<div>hi</div>')
expect(vm.$children.length).toBe(1)
done()
}
})
it('as root', done => {
const vm = new Vue({
template: '<test></test>',

Loading…
Cancel
Save