Skip to content

高级:拓展、覆盖组件

本示例展示如何在 ProForm 中拓展自定义组件覆盖内置组件类型提示,对应 /antd-vue-pro/components/pro-form/#高级-typescript-类型推导与覆盖 的进阶用法。

关键思路

  1. 运行时:使用 ProComponentProvider 注册 componentMap,让 component: 'text' 能正确渲染。
  2. 类型提示:通过 声明合并 扩展 ComponentMap,让字段 component 自动获得类型推导。
  3. 覆盖提示:在 ComponentMap 中重写 input,即可替换默认组件的 Props 类型提示。
  4. 全局默认:通过 componentVars 设置 textmodelProp 默认值。

表单展示


高级:拓展、覆盖组件
这里会渲染 CustomInput
很长很长的一段描述
这里会渲染 TypographyText

代码实现

vue
<script lang="ts" setup>
import { Card, TypographyText } from 'ant-design-vue';
import { ProComponentProvider, ProForm, useForm } from '@qin-ui/antd-vue-pro';
import CustomInput from '../custom-component/CustomInput.vue';

type FormData = {
  name: string;
  description: string;
};

const form = useForm<FormData>(
  { name: '', description: '很长很长的一段描述' },
  [
    {
      label: '输入框(覆盖 input)',
      path: 'name',
      component: 'input',
      extra: '这里会渲染 CustomInput',
    },
    {
      label: '文本(拓展自定义组件 text)',
      path: 'description',
      component: 'text', 
      extra: '这里会渲染 TypographyText',
    },
  ]
);

const componentMap = {
  text: TypographyText, 
  input: CustomInput, 
};

const componentVars = {
  text: {
    modelProp: 'content', // 为 TypographyText 添加全局默认modelProp
  },
};
</script>

<template>
  <ProComponentProvider
    :component-map="componentMap"
    :component-vars="componentVars"
  >
    <Card title="高级:拓展、覆盖组件">
      <ProForm :form="form" />
    </Card>
  </ProComponentProvider>
</template>

CustomInput 代码实现

vue
<script lang="ts" setup>
const value = defineModel<string>('value', { default: '' });
</script>

<template>
  <!-- From Uiverse.io by ErzenXz -->
  <input
    type="text"
    class="input"
    v-bind="$attrs"
    :value="value"
    @input="e => (value = (e.target as any)?.value)"
  />
</template>

<style scoped lang="css">
/* From Uiverse.io by ErzenXz */
.input {
  width: 100%;
  height: 45px;
  padding: 12px;
  border: 1.5px solid lightgrey;
  border-radius: 12px;
  outline: none;
  box-shadow: 0px 0px 20px -18px;
  transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
}

.input:hover {
  border: 2px solid lightgrey;
  box-shadow: 0px 0px 20px -17px;
}

.input:active {
  transform: scale(0.95);
}

.input:focus {
  border: 2px solid grey;
}
</style>

类型声明示例

ts
import 'antd-vue-pro';
import type CustomInput from '../custom-component/CustomInput.vue';
import type { TypographyText } from 'ant-design-vue';

declare module 'antd-vue-pro' {
  interface ComponentMap {
    text: typeof TypographyText;
    input: typeof CustomInput;
  }
}