kt-template-admin/skills/references/components/business/api-component.md
2026-05-16 17:30:35 +08:00

4.7 KiB

Vben ApiComponent API组件包装器

用于包装其它组件,为目标组件提供自动获取远程数据的能力。

基础用法

包装 Select 组件,自动获取远程选项:

<script setup lang="ts">
import { ApiComponent } from '@vben/common-ui';
import { Select } from 'ant-design-vue';

async function fetchOptions() {
  const res = await getUserListApi();
  return res.data;
}
</script>

<template>
  <ApiComponent
    v-model="selectedValue"
    :api="fetchOptions"
    :component="Select"
    label-field="name"
    value-field="id"
  />
</template>

包装级联选择器

<script setup lang="ts">
import { ApiComponent } from '@vben/common-ui';
import { Cascader } from 'ant-design-vue';

async function fetchTreeData() {
  const res = await getRegionTreeApi();
  return res.data;
}
</script>

<template>
  <ApiComponent
    v-model="selectedRegion"
    :api="fetchTreeData"
    :component="Cascader"
    :immediate="false"
    children-field="children"
    loading-slot="suffixIcon"
    visible-event="onDropdownVisibleChange"
  />
</template>

请求参数

<script setup lang="ts">
const params = ref({ type: 'user' });

async function fetchOptions(params) {
  const res = await getOptionsApi(params);
  return res.data;
}
</script>

<template>
  <ApiComponent
    v-model="value"
    :api="fetchOptions"
    :params="params"
    :component="Select"
  />
</template>

请求前后处理

<script setup lang="ts">
async function beforeFetch(params) {
  // 请求前处理参数
  return { ...params, status: 1 };
}

async function afterFetch(data) {
  // 请求后处理数据
  return data.map(item => ({
    ...item,
    label: `${item.name} (${item.code})`,
  }));
}
</script>

<template>
  <ApiComponent
    v-model="value"
    :api="fetchOptions"
    :component="Select"
    :before-fetch="beforeFetch"
    :after-fetch="afterFetch"
  />
</template>

自动选择选项

<template>
  <!-- 自动选择第一个选项 -->
  <ApiComponent
    v-model="value"
    :api="fetchOptions"
    :component="Select"
    auto-select="first"
  />

  <!-- 有且仅有一个选项时自动选择 -->
  <ApiComponent
    v-model="value"
    :api="fetchOptions"
    :component="Select"
    auto-select="one"
  />
</template>

Props 属性

属性名 描述 类型 默认值
modelValue 当前值 any -
component 目标组件 Component -
api 获取数据的函数 (arg?) => Promise<any> -
params 传递给api的参数 object -
resultField 从结果中提取数组的字段名 string -
labelField label字段名 string label
valueField value字段名 string value
childrenField 子级数据字段名 string -
optionsPropName 目标组件接收options的属性名 string options
modelPropName 目标组件的双向绑定属性名 string modelValue
immediate 是否立即调用api boolean true
alwaysLoad 每次显示时重新请求 boolean false
beforeFetch 请求前的回调 (params) => any -
afterFetch 请求后的回调 (data) => any -
options 直接传入选项数据 OptionsItem[] -
visibleEvent 触发请求的事件名 string -
loadingSlot 显示loading的插槽名 string -
numberToString 将value从数字转为string boolean false
autoSelect 自动设置选项 'first' | 'last' | 'one' false

Methods 方法

方法 描述 类型
getComponentRef 获取被包装组件的实例 () => T
updateParam 设置接口请求参数 (params) => void
getOptions 获取已加载的选项数据 () => OptionsItem[]
getValue 获取当前值 () => any

并发和缓存

使用 Tanstack Query 包装接口请求,实现并发控制和缓存:

import { useQuery } from '@tanstack/vue-query';

function useUserOptions() {
  return useQuery({
    queryKey: ['user-options'],
    queryFn: () => getUserListApi(),
    staleTime: 5 * 60 * 1000, // 5分钟缓存
  });
}

适配器配置

在应用适配器中预包装组件:

// src/adapter/component.ts
import { ApiComponent } from '@vben/common-ui';
import { Select, TreeSelect } from 'ant-design-vue';

const components = {
  ApiSelect: (props, { attrs, slots }) => {
    return h(ApiComponent, {
      ...props,
      ...attrs,
      component: Select,
    }, slots);
  },
  ApiTreeSelect: (props, { attrs, slots }) => {
    return h(ApiComponent, {
      ...props,
      ...attrs,
      component: TreeSelect,
      childrenField: 'children',
    }, slots);
  },
};