setup()

in packages/element/src/form-item/index.ts [142:498]


  setup(props, { slots, refs }) {
    const active = ref(false)
    const deepLayoutRef = useFormLayout()

    const prefixCls = `${stylePrefix}-form-item`

    const { elRef: containerRef, elRefBinder } = useCompatRef(refs)
    const overflow = useOverflow(containerRef)

    provide(FormLayoutShallowContext, ref(null))

    return () => {
      const gridStyles: Record<string, any> = {}

      const deepLayout = deepLayoutRef.value
      const {
        label,
        colon = deepLayout.colon ?? true,
        layout = deepLayout.layout ?? 'horizontal',
        tooltip,
        labelStyle = {},
        labelWrap = deepLayout.labelWrap ?? false,
        labelWidth = deepLayout.labelWidth,
        wrapperWidth = deepLayout.wrapperWidth,
        labelCol = deepLayout.labelCol,
        wrapperCol = deepLayout.wrapperCol,
        wrapperAlign = deepLayout.wrapperAlign ?? 'left',
        wrapperWrap = deepLayout.wrapperWrap,
        wrapperStyle = {},
        fullness = deepLayout.fullness,
        addonBefore,
        addonAfter,
        size = deepLayout.size,
        extra,
        feedbackText,
        feedbackLayout = deepLayout.feedbackLayout ?? 'loose',
        tooltipLayout = deepLayout.tooltipLayout ?? 'icon',
        feedbackStatus,
        feedbackIcon,
        asterisk,
        bordered = deepLayout.bordered,
        inset = deepLayout.inset,
      } = props
      const labelAlign =
        deepLayout.layout === 'vertical'
          ? props.labelAlign ?? deepLayout.labelAlign ?? 'left'
          : props.labelAlign ?? deepLayout.labelAlign ?? 'right'

      // 固定宽度
      let enableCol = false
      if (labelWidth || wrapperWidth) {
        if (labelWidth) {
          labelStyle.width = `${labelWidth}px`
          labelStyle.maxWidth = `${labelWidth}px`
        }
        if (wrapperWidth) {
          wrapperStyle.width = `${wrapperWidth}px`
          wrapperStyle.maxWidth = `${wrapperWidth}px`
        }
        // 栅格模式
      } else if (labelCol || wrapperCol) {
        enableCol = true
      }

      const formatChildren =
        feedbackLayout === 'popover'
          ? h(
              'el-popover',
              {
                props: {
                  disabled: !feedbackText,
                  placement: 'top',
                },
              },
              {
                reference: () =>
                  h('div', {}, { default: () => slots.default?.() }),
                default: () => [
                  h(
                    'div',
                    {
                      class: {
                        [`${prefixCls}-${feedbackStatus}-help`]:
                          !!feedbackStatus,
                        [`${prefixCls}-help`]: true,
                      },
                    },
                    {
                      default: () => [
                        feedbackStatus &&
                        ['error', 'success', 'warning'].includes(feedbackStatus)
                          ? ICON_MAP[
                              feedbackStatus as 'error' | 'success' | 'warning'
                            ]()
                          : '',
                        resolveComponent(feedbackText),
                      ],
                    }
                  ),
                ],
              }
            )
          : slots.default?.()

      const renderLabelText = () => {
        const labelChildren = h(
          'div',
          {
            class: `${prefixCls}-label-content`,
            ref: elRefBinder,
          },
          {
            default: () => [
              asterisk &&
                h(
                  'span',
                  { class: `${prefixCls}-asterisk` },
                  { default: () => ['*'] }
                ),
              h('label', {}, { default: () => [resolveComponent(label)] }),
            ],
          }
        )
        const isTextTooltip = tooltip && tooltipLayout === 'text'
        if (isTextTooltip || overflow.value) {
          return h(
            Tooltip,
            {
              props: {
                placement: 'top',
              },
            },
            {
              default: () => [labelChildren],
              content: () =>
                h(
                  'div',
                  {},
                  {
                    default: () => [
                      overflow.value && resolveComponent(label),
                      isTextTooltip && resolveComponent(tooltip),
                    ],
                  }
                ),
            }
          )
        } else {
          return labelChildren
        }
      }
      const renderTooltipIcon = () => {
        if (tooltip && tooltipLayout === 'icon') {
          return h(
            'span',
            {
              class: `${prefixCls}-label-tooltip`,
            },
            {
              default: () => [
                h(
                  Tooltip,
                  {
                    props: {
                      placement: 'top',
                    },
                  },
                  {
                    default: () => [h('i', { class: 'el-icon-info' }, {})],
                    content: () =>
                      h(
                        'div',
                        {
                          class: `${prefixCls}-label-tooltip-content`,
                        },
                        {
                          default: () => [resolveComponent(tooltip)],
                        }
                      ),
                  }
                ),
              ],
            }
          )
        }
      }
      const renderLabel =
        label &&
        h(
          'div',
          {
            class: {
              [`${prefixCls}-label`]: true,
              [`${prefixCls}-label-tooltip`]:
                (tooltip && tooltipLayout === 'text') || overflow.value,
              [`${prefixCls}-item-col-${labelCol}`]: enableCol && !!labelCol,
            },
            style: labelStyle,
          },
          {
            default: () => [
              // label content
              renderLabelText(),
              // label tooltip
              renderTooltipIcon(),
              // label colon
              label &&
                h(
                  'span',
                  {
                    class: `${prefixCls}-colon`,
                  },
                  { default: () => [colon ? ':' : ''] }
                ),
            ],
          }
        )

      const renderFeedback =
        !!feedbackText &&
        feedbackLayout !== 'popover' &&
        feedbackLayout !== 'none' &&
        h(
          'div',
          {
            class: {
              [`${prefixCls}-${feedbackStatus}-help`]: !!feedbackStatus,
              [`${prefixCls}-help`]: true,
              [`${prefixCls}-help-enter`]: true,
              [`${prefixCls}-help-enter-active`]: true,
            },
          },
          { default: () => [resolveComponent(feedbackText)] }
        )

      const renderExtra =
        extra &&
        h(
          'div',
          { class: `${prefixCls}-extra` },
          { default: () => [resolveComponent(extra)] }
        )
      const renderContent = h(
        'div',
        {
          class: {
            [`${prefixCls}-control`]: true,
            [`${prefixCls}-item-col-${wrapperCol}`]: enableCol && !!wrapperCol,
          },
        },
        {
          default: () => [
            h(
              'div',
              { class: `${prefixCls}-control-content` },
              {
                default: () => [
                  addonBefore &&
                    h(
                      'div',
                      { class: `${prefixCls}-addon-before` },
                      {
                        default: () => [resolveComponent(addonBefore)],
                      }
                    ),
                  h(
                    'div',
                    {
                      class: {
                        [`${prefixCls}-control-content-component`]: true,
                        [`${prefixCls}-control-content-component-has-feedback-icon`]:
                          !!feedbackIcon,
                      },
                      style: wrapperStyle,
                    },
                    {
                      default: () => [
                        formatChildren,
                        feedbackIcon &&
                          h(
                            'div',
                            { class: `${prefixCls}-feedback-icon` },
                            {
                              default: () => [
                                typeof feedbackIcon === 'string'
                                  ? h('i', { class: feedbackIcon }, {})
                                  : resolveComponent(feedbackIcon),
                              ],
                            }
                          ),
                      ],
                    }
                  ),
                  addonAfter &&
                    h(
                      'div',
                      { class: `${prefixCls}-addon-after` },
                      {
                        default: () => [resolveComponent(addonAfter)],
                      }
                    ),
                ],
              }
            ),
            renderFeedback,
            renderExtra,
          ],
        }
      )
      return h(
        'div',
        {
          style: {
            ...gridStyles,
          },
          attrs: {
            'data-grid-span': props.gridSpan,
          },
          class: {
            [`${prefixCls}`]: true,
            [`${prefixCls}-layout-${layout}`]: true,
            [`${prefixCls}-${feedbackStatus}`]: !!feedbackStatus,
            [`${prefixCls}-feedback-has-text`]: !!feedbackText,
            [`${prefixCls}-size-${size}`]: !!size,
            [`${prefixCls}-feedback-layout-${feedbackLayout}`]:
              !!feedbackLayout,
            [`${prefixCls}-fullness`]: !!fullness || !!inset || !!feedbackIcon,
            [`${prefixCls}-inset`]: !!inset,
            [`${prefixCls}-active`]: active.value,
            [`${prefixCls}-inset-active`]: !!inset && active.value,
            [`${prefixCls}-label-align-${labelAlign}`]: true,
            [`${prefixCls}-control-align-${wrapperAlign}`]: true,
            [`${prefixCls}-label-wrap`]: !!labelWrap,
            [`${prefixCls}-control-wrap`]: !!wrapperWrap,
            [`${prefixCls}-bordered-none`]:
              bordered === false || !!inset || !!feedbackIcon,
            [`${props.className}`]: !!props.className,
          },
          on: {
            focus: () => {
              if (feedbackIcon || inset) {
                active.value = true
              }
            },
            blur: () => {
              if (feedbackIcon || inset) {
                active.value = false
              }
            },
          },
        },
        {
          default: () => [renderLabel, renderContent],
        }
      )
    }
  },