Skip to content

Commit 205e164

Browse files
authored
feat(element): support element-ui slot (#2162)
1 parent cdf8405 commit 205e164

File tree

13 files changed

+139
-89
lines changed

13 files changed

+139
-89
lines changed

packages/element/src/__builtins__/shared/get-component-by-tag.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

packages/element/src/__builtins__/shared/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export * from './get-component-by-tag'
1+
export * from './transform-component'
22
export * from './resolve-component'
33
export * from './create-context'
44
export * from './utils'

packages/element/src/__builtins__/shared/resolve-component.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
1+
import { Component } from 'vue'
12
import { h, toRaw } from '@vue/composition-api'
2-
import { Component, VNode } from 'vue'
3+
import { SlotTypes } from '.'
4+
import { isVnode } from './utils'
35

46
export const resolveComponent = (
5-
child?:
6-
| Component
7-
| string
8-
| number
9-
| boolean
10-
| ((...args: any[]) => VNode[] | VNode),
7+
child?: SlotTypes,
118
props?: Record<string, any>
129
) => {
1310
if (child) {
14-
if (
15-
typeof child === 'string' ||
16-
typeof child === 'number' ||
17-
typeof child === 'boolean'
18-
) {
11+
if (typeof child === 'string' || typeof child === 'number') {
1912
return child
2013
} else if (typeof child === 'function') {
2114
return (child as Function)(props)
15+
} else if (isVnode(child)) {
16+
return child
2217
} else {
23-
return h(toRaw(child), { props })
18+
return h(toRaw(child as Component), { props })
2419
}
2520
}
2621

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { Component } from 'vue'
2+
import { merge } from '@formily/shared'
3+
import { h } from '@formily/vue'
4+
import { isVue2, h as hInVue2, defineComponent } from 'vue-demi'
5+
6+
type ListenersTransformRules = Record<string, string>
7+
8+
export const transformComponent = <T extends Record<string, any>>(
9+
tag: any,
10+
transformRules?: ListenersTransformRules,
11+
defaultProps?: Partial<T>
12+
): Component<T> | any => {
13+
if (isVue2) {
14+
return defineComponent({
15+
setup(props, { attrs, slots, listeners }) {
16+
return () => {
17+
const data = {
18+
attrs: {
19+
...attrs,
20+
},
21+
on: {
22+
...listeners,
23+
},
24+
}
25+
26+
if (transformRules) {
27+
const transformListeners = transformRules
28+
Object.keys(transformListeners).forEach((extract) => {
29+
if (data.on !== undefined) {
30+
data.on[transformListeners[extract]] = listeners[extract]
31+
}
32+
})
33+
}
34+
if (defaultProps) {
35+
data.attrs = merge(defaultProps, data.attrs)
36+
}
37+
38+
return h(tag, data, slots)
39+
}
40+
},
41+
})
42+
} else {
43+
return defineComponent({
44+
setup(props, { attrs, slots }) {
45+
return () => {
46+
let data = {
47+
...attrs,
48+
}
49+
if (transformRules) {
50+
const listeners = transformRules
51+
Object.keys(listeners).forEach((extract) => {
52+
const event = listeners[extract]
53+
data[`on${event[0].toUpperCase()}${event.slice(1)}`] =
54+
attrs[`on${extract[0].toUpperCase()}${extract.slice(1)}`]
55+
})
56+
}
57+
if (defaultProps) {
58+
data = merge(defaultProps, data)
59+
}
60+
return h(tag, data, slots)
61+
}
62+
},
63+
})
64+
}
65+
}

packages/element/src/__builtins__/shared/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ export function isValidElement(element) {
99
) // remove text node
1010
}
1111

12+
export function isVnode(element: any): boolean {
13+
return (
14+
element &&
15+
typeof element === 'object' &&
16+
'componentOptions' in element &&
17+
'context' in element &&
18+
element.tag !== undefined
19+
)
20+
}
21+
1222
export function isVueOptions(options) {
1323
return (
1424
options &&

packages/element/src/checkbox/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { connect, mapProps, h, mapReadPretty } from '@formily/vue'
22
import { defineComponent, PropType } from '@vue/composition-api'
33
import {
44
composeExport,
5-
getComponentByTag,
5+
transformComponent,
66
resolveComponent,
77
SlotTypes,
88
} from '../__builtins__/shared'
@@ -83,7 +83,7 @@ export type CheckboxGroupProps = ElCheckboxGroupProps & {
8383
optionType: 'default' | 'button'
8484
}
8585

86-
const TransformElCheckboxGroup = getComponentByTag(ElCheckboxGroup, {
86+
const TransformElCheckboxGroup = transformComponent(ElCheckboxGroup, {
8787
change: 'input',
8888
})
8989

packages/element/src/date-picker/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getComponentByTag } from '../__builtins__/shared'
1+
import { transformComponent } from '../__builtins__/shared'
22
import { connect, mapProps, mapReadPretty } from '@formily/vue'
33

44
import type { DatePicker as ElDatePickerProps } from 'element-ui'
@@ -7,9 +7,12 @@ import { PreviewText } from '../preview-text'
77

88
export type DatePickerProps = ElDatePickerProps
99

10-
const TransformElDatePicker = getComponentByTag<DatePickerProps>(ElDatePicker, {
11-
change: 'input',
12-
})
10+
const TransformElDatePicker = transformComponent<DatePickerProps>(
11+
ElDatePicker,
12+
{
13+
change: 'input',
14+
}
15+
)
1316

1417
const getDefaultFormat = (props, formatType = 'format') => {
1518
const type = props.type

packages/element/src/input-number/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getComponentByTag } from '../__builtins__/shared'
1+
import { transformComponent } from '../__builtins__/shared'
22
import { connect, mapProps, mapReadPretty } from '@formily/vue'
33

44
import type { InputNumber as _ElInputNumberProps } from 'element-ui'
@@ -7,7 +7,7 @@ import { PreviewText } from '../preview-text'
77

88
export type InputNumberProps = _ElInputNumberProps
99

10-
const TransformElInputNumber = getComponentByTag<InputNumberProps>(
10+
const TransformElInputNumber = transformComponent<InputNumberProps>(
1111
ElInputNumber,
1212
{
1313
change: 'input',

packages/element/src/input/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { composeExport, getComponentByTag } from '../__builtins__/shared'
1+
import { composeExport, transformComponent } from '../__builtins__/shared'
22
import { connect, mapProps, mapReadPretty } from '@formily/vue'
33
import { PreviewText } from '../preview-text'
44
import type { Input as ElInputProps } from 'element-ui'
55
import { Input as ElInput } from 'element-ui'
66

77
export type InputProps = ElInputProps
88

9-
const TransformElInput = getComponentByTag<InputProps>(ElInput, {
9+
const TransformElInput = transformComponent<InputProps>(ElInput, {
1010
change: 'input',
1111
})
1212

packages/element/src/radio/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { connect, mapProps, h, mapReadPretty } from '@formily/vue'
22
import { defineComponent, PropType } from '@vue/composition-api'
33
import {
44
composeExport,
5-
getComponentByTag,
5+
transformComponent,
66
resolveComponent,
77
SlotTypes,
88
} from '../__builtins__/shared'
@@ -31,7 +31,7 @@ export type RadioGroupProps = ElRadioGroupProps & {
3131

3232
export type RadioProps = ElRadioProps
3333

34-
const TransformElRadioGroup = getComponentByTag(ElRadioGroup, {
34+
const TransformElRadioGroup = transformComponent(ElRadioGroup, {
3535
change: 'input',
3636
})
3737

packages/element/src/select/index.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ import type {
77
Option as ElOptionProps,
88
} from 'element-ui'
99
import { Select as ElSelect, Option as ElOption } from 'element-ui'
10+
import { resolveComponent, SlotTypes } from '../__builtins__'
1011

1112
export type SelectProps = ElSelectProps & {
12-
options?: Array<ElOptionProps | string>
13+
options?: Array<
14+
Omit<ElOptionProps, 'label'> & {
15+
label: SlotTypes
16+
}
17+
>
1318
}
1419

1520
const SelectOption = defineComponent<SelectProps>({
@@ -26,11 +31,30 @@ const SelectOption = defineComponent<SelectProps>({
2631
if (typeof option === 'string') {
2732
return h(
2833
ElOption,
29-
{ props: { label: option, value: option } },
30-
{}
34+
{ props: { value: option } },
35+
{
36+
default: () => [
37+
resolveComponent(slots?.option ?? option, { option }),
38+
],
39+
}
3140
)
3241
} else {
33-
return h(ElOption, { props: option }, {})
42+
return h(
43+
ElOption,
44+
{
45+
props: {
46+
...option,
47+
label: '',
48+
},
49+
},
50+
{
51+
default: () => [
52+
resolveComponent(slots?.option ?? option.label, {
53+
option,
54+
}),
55+
],
56+
}
57+
)
3458
}
3559
}),
3660
}

packages/element/src/time-picker/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
import { getComponentByTag } from '../__builtins__/shared'
1+
import { transformComponent } from '../__builtins__/shared'
22
import { connect, mapProps, mapReadPretty } from '@formily/vue'
33
import { PreviewText } from '../preview-text'
44
import type { TimePicker as ElTimePickerProps } from 'element-ui'
55
import { TimePicker as ElTimePicker } from 'element-ui'
66

77
export type TimePickerProps = ElTimePickerProps
88

9-
const TransformElTimePicker = getComponentByTag<TimePickerProps>(ElTimePicker, {
10-
change: 'input',
11-
})
9+
const TransformElTimePicker = transformComponent<TimePickerProps>(
10+
ElTimePicker,
11+
{
12+
change: 'input',
13+
}
14+
)
1215

1316
export const TimePicker = connect(
1417
TransformElTimePicker,

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19619,6 +19619,11 @@ vue-frag@^1.1.4:
1961919619
resolved "https://registry.yarnpkg.com/vue-frag/-/vue-frag-1.1.5.tgz#1158f92361dff2c312e00b8ca85334c329e566e7"
1962019620
integrity sha512-g+PP9pjW1gnrmPjy2Sa5jK/bfxYHK8Hgt1sVs/Y/7KT+srGJUwtGNwXNTUvWv/zJ2yGcvJVEH98eIrICyZX9Ng==
1962119621

19622+
vue-hoc@^0.4.7:
19623+
version "0.4.7"
19624+
resolved "https://registry.nlark.com/vue-hoc/download/vue-hoc-0.4.7.tgz#4d3322ba89b8b0e42b19045ef536c21d948a4fac"
19625+
integrity sha1-TTMiuom4sOQrGQRe9TbCHZSKT6w=
19626+
1962219627
vue-hot-reload-api@^2.3.0:
1962319628
version "2.3.4"
1962419629
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"

0 commit comments

Comments
 (0)