Skip to content

高级:拓展、覆盖组件

本示例展示如何在 ProForm 中拓展自定义组件并覆盖内置组件。

表单展示


高级:拓展、覆盖组件
输入框(覆盖 input)
文本(拓展组件 text)
很长很长的一段描述

代码实现

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

declare module '@qin-ui/element-plus-pro' {
  interface ComponentMap {
    text: typeof TextDisplay;
    input: typeof CustomInput;
  }
}

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: '这里会渲染 TextDisplay',
    },
  ]
);

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

const componentVars = {
  text: {
    modelProp: 'content',
  },
};
</script>

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

TextDisplay 代码实现

vue
<script lang="ts" setup>
defineProps<{ content?: string; placeholder?: string }>();
</script>

<template>
  <span class="text-display">
    {{ content || placeholder || '自定义 text 组件(modelProp=content)' }}
  </span>
</template>

<style scoped>
.text-display {
  color: #606266;
}
</style>

CustomInput 代码实现

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

<template>
  <input
    type="text"
    class="input"
    v-bind="$attrs"
    :value="value"
    @input="e => (value = (e.target as HTMLInputElement)?.value || '')"
  />
</template>

<style scoped>
.input {
  width: 100%;
  height: 40px;
  padding: 8px 12px;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  outline: none;
}

.input:focus {
  border-color: #409eff;
}
</style>