Browse Source

fix(types): accept primatives and falsy values in createElement children (#9154)

fixes #8498
dev
Kael 6 years ago
committed by Evan You
parent
commit
d780dd2e2a
  1. 22
      types/test/options-test.ts
  2. 13
      types/vnode.d.ts

22
types/test/options-test.ts

@ -281,6 +281,12 @@ Vue.component('provide-function', {
}) })
}) })
Vue.component('component-with-slot', {
render (h): VNode {
return h('div', this.$slots.default)
}
})
Vue.component('component-with-scoped-slot', { Vue.component('component-with-scoped-slot', {
render (h) { render (h) {
interface ScopedSlotProps { interface ScopedSlotProps {
@ -301,6 +307,12 @@ Vue.component('component-with-scoped-slot', {
h('child', { h('child', {
// Passing down all slots from parent // Passing down all slots from parent
scopedSlots: this.$scopedSlots scopedSlots: this.$scopedSlots
}),
h('child', {
// Passing down single slot from parent
scopedSlots: {
default: this.$scopedSlots.default
}
}) })
]) ])
}, },
@ -320,16 +332,22 @@ Vue.component('narrow-array-of-vnode-type', {
render (h): VNode { render (h): VNode {
const slot = this.$scopedSlots.default!({}) const slot = this.$scopedSlots.default!({})
if (typeof slot === 'string') { if (typeof slot === 'string') {
// <template slot-scope="data">bare string</template>
return h('span', slot) return h('span', slot)
} else if (Array.isArray(slot)) { } else if (Array.isArray(slot)) {
// template with multiple children
const first = slot[0] const first = slot[0]
if (!Array.isArray(first) && typeof first !== 'string') { if (!Array.isArray(first) && typeof first !== 'string' && first) {
return first return first
} else { } else {
return h() return h()
} }
} else { } else if (slot) {
// <div slot-scope="data">bare VNode</div>
return slot return slot
} else {
// empty template, slot === undefined
return h()
} }
} }
}) })

13
types/vnode.d.ts

@ -1,9 +1,14 @@
import { Vue } from "./vue"; import { Vue } from "./vue";
export type ScopedSlot = (props: any) => VNodeChildrenArrayContents | VNode | string; // Scoped slots can technically return anything if used from
// a render function, but this is "good enough" for templates
export type ScopedSlot = (props: any) => ScopedSlotChildren;
export type ScopedSlotChildren = ScopedSlotArrayContents | VNode | string | undefined;
export interface ScopedSlotArrayContents extends Array<ScopedSlotChildren> {}
export type VNodeChildren = VNodeChildrenArrayContents | [ScopedSlot] | string; // Relaxed type compatible with $createElement
export interface VNodeChildrenArrayContents extends Array<VNode | string | VNodeChildrenArrayContents> {} export type VNodeChildren = VNodeChildrenArrayContents | [ScopedSlot] | string | boolean | null | undefined;
export interface VNodeChildrenArrayContents extends Array<VNodeChildren | VNode> {}
export interface VNode { export interface VNode {
tag?: string; tag?: string;
@ -27,7 +32,7 @@ export interface VNodeComponentOptions {
Ctor: typeof Vue; Ctor: typeof Vue;
propsData?: object; propsData?: object;
listeners?: object; listeners?: object;
children?: VNodeChildren; children?: VNode[];
tag?: string; tag?: string;
} }

Loading…
Cancel
Save