Skip to content

高级:拓展、覆盖组件

当内置的组件无法满足所有需求时,你可能需要编写自己的自定义组件。虽然你可以使用 component: 'custom' 和传入渲染函数来解决,但如果你有一个全局复用的组件,你可能希望它像内置的 fieldpicker 一样被优雅地调用。

你可以通过在 ProComponentProvider 中注册 componentMap 来实现这一点,并通过 TypeScript 的模块扩充(Module Augmentation)来获得完美的类型提示。

运行时渲染演示


很长很长很长很长很长很长很长很长很长很长很长很长很长很长的一段描述

1. 扩充类型定义

在你的项目中(例如 src/typings/vant-pro.d.tsenv.d.ts 中),对 @qin-ui/vant-proComponentMap 接口进行声明合并。

ts
// env.d.ts
import MyUploadComponent from '@/components/MyUpload.vue';
import { TextEllipsis } from 'vant';

declare module '@qin-ui/vant-pro' {
  // 扩充 ComponentMap
  interface ComponentMap {
    'my-upload': typeof MyUploadComponent;
    textEllipsis: typeof TextEllipsis;
  }
}

2. 代码实现

在运行时使用 ProComponentProvider 注入实际的组件实例,并使用 useForm 进行渲染:

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

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

const form = useForm<FormData>(
  {
    name: '',
    description:
      '很长很长很长很长很长很长很长很长很长很长很长很长很长很长的一段描述',
  },
  [
    {
      label: '自定义输入框(覆盖 field)',
      path: 'name',
      component: 'field',
    },
    {
      label: '自定义拓展组件',
      path: 'description',
      component: 'textEllipsis',
      modelProp: 'content',
    },
  ]
);

const componentMap = {
  field: CustomInput, 
  textEllipsis: TextEllipsis, 
};

const componentVars = {
  field: {
    // 全局默认
  },
};
</script>

<template>
  <ProComponentProvider
    :component-map="componentMap"
    :component-vars="componentVars"
  >
    <div class="demo-wrapper">
      <ProForm :form="form" label-width="fit-content" />
    </div>
  </ProComponentProvider>
</template>

<style scoped>
.demo-wrapper {
  max-width: 430px;
  padding: 16px;
  overflow: hidden;
  background: #f7f8fa;
  border-radius: 8px;
}
</style>