UNPKG

formily-request-monorepo

Version:

A flexible, lightweight, non-intrusive plugin for extending formily schema request data.

379 lines (305 loc) 9.68 kB
--- nav: { title: 'API', order: 2 } --- # API 插件默认导出 FormilyRequest 的单例对象,实例上面挂载了 use、register 方法。 调用实例方法后,就可以在 schema 中使用注册后的字段(默认为:`x-request`)了。 ## 实例方法 ### `use()` 插件的核心原理是使用 `Schema.registerPatches` 方法将 `x-request` 注入到 schema 中。 为了减少包大小,需要将构造函数 `Schema` 通过 use 函数传入插件内部。 构造函数来自 `@formily/react``@formily/vue` 包: ```ts import { Schema } from '@formily/react'; // or @formily/vue import fxr from 'formily-request'; fxr.use(Schema); ``` ### `register()` 通过 register 可以注册 JSON Schema 的配置字段 或者 设置全局配置,类型如下: ```typescript register(): void; register(fieldKey: `x-${string}`): void; register(globalConfig: GlobalXRequest): void; register(fieldKey: `x-${string}`, globalConfig: GlobalXRequest): void; ``` register 是一个多参数函数,支持以下几种参数传入方式: - 无参数:默认使用 `x-request` 注册字段; - 一个参数:注册指定字段,例如 `x-fetch`,或者传入全局配置; - 两个参数:注册指定字段和全局配置。 ```typescript import fxr from 'formily-request'; fxr.register({ // 全局基础URL baseURL: 'https://api.example.com', // 全局错误处理 onError: (err) => { console.error(err); message.error('操作失败,请重试'); }, // 全局调试模式 debug: process.env.NODE_ENV === 'development', // 全局静态参数 params: { token: 'xxx', }, }); ``` ## 字段配置 字段配置是指在 `JSON Schema` 中配置的 `x-reqeust` 对象,类型定义如下: ```typescript interface XRequest extends RequestInit { baseURL?: string; url?: string; method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; params?: Record<string, any>; format?: (data: unknown) => any[]; ready?: boolean | ((request: XRequest) => boolean); mountLoad?: boolean; service?: (params: XRequest['params']) => Promise<unknown>; customService?: (config: XRequest) => Promise<unknown>; debug?: boolean; onSuccess?: (data: unknown, request: XRequest) => void; staticParams?: Record<string, any>; } ``` :::info{title=RequestInit} 由于 formily-request 默认使用 [fetch](https://mdn.org.cn/en-US/docs/Web/API/Window/fetch#google_vignette) 发起请求,所以配置的类型会继承 fetch 的第 2 个参数 [RequestInit](https://mdn.org.cn/en-US/docs/Web/API/RequestInit),这样的设计可以最大限度使用 fetch 配置,可以在全局或字段处配置 fetch 自带配置,例如:`headers`, `credentials` 等等。 ::: ### `baseURL` - **类型**: `string` - **必填**: 否 - **说明**: 接口前缀,配合 `url` 字段使用,通常配置在全局。 - **示例**: ```typescript fxr.register({ baseURL: process.env.BASE_URL, // 例如:/api }); const schema = { 'x-request': { url: '/users', // 最终请求地址为 /api/users }, }; ``` ### `url` - **类型**: `string` - **必填**: 是 - **说明**: 接口请求地址,使用 formily-request 默认的 fetch 发起请求时,必须要传入该字段。 - **示例**: ```typescript { "x-request": { url: "https://api.example.com/users" // 或配合 baseURL 使用相对路径 } } ``` ### `method` - **类型**: `'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'` - **默认值**: `'GET'` - **说明**: HTTP 请求方法,配合 `url` 字段使用。 - **示例**: ```typescript { "x-request": { url: "/api/users", method: "POST", params: { name: "John" } // 如果 method 为 post,使用 fetch 发起请求时,params 会被序列化后赋值给 body } } ``` ### `params` - **类型**: `Record<string, any>` - **必填**: 否 - **说明**: 动态请求参数,可以使用表达式动态生成 - **示例**: ```typescript { "x-request": { url: "/api/search", params: { keyword: "{{ $self.value }}", // 使用当前字段值作为搜索关键词 type: "user" } } } ``` ### `format` - **类型**: `(res: unknown) => any[]` - **必填**: 否 - **说明**: 数据格式化函数,用于将接口返回的数据转换为组件所需的格式。 - **示例**: ```typescript { "x-request": { url: "/api/users", format: '{{ (res) => res?.data?.map(user => ({ label: user.name, value: user.id } }}' } } ``` :::info{title=注意} 无论是默认的 fetch,还是 service、customService,获取到的接口数据,都会经过 format 函数处理,然后被应用到 field.dataSource。<br /> 如果自行处理过数据并适配当前组件,可以不配置 format。 ::: ### `ready` - **类型**: `boolean | ((request: XRequest) => boolean)` - **必填**: 否 - **说明**: 是否发起请求,值为 `false` 或返回 `false` 的函数时,将阻止请求发送。 - **示例**: ```typescript { "x-request": { url: "/api/data", ready: '{{ $self.visible }}', // 当前字段可见时才会发起请求 ready: '{{ request => !!request?.params?.id }}' // 当前请求参数id存在时才会发起请求 } } ``` ### `mountLoad` - **类型**: `boolean` - **默认值**: `true` - **说明**: 控制是否在组件挂载后发起请求。默认情况下,组件挂载后会自动发起请求。 - **示例**: ```typescript { "x-request": { url: "/api/options", mountLoad: false // 禁用挂载后请求,需要手动触发数据加载 } } ``` ### `service` - **类型**: `(params: any) => Promise<unknown>` - **必填**: 否 - **说明**: 自定义请求服务,可以使用自定义的请求方法替代默认的 fetch 请求。 - **示例**: ```typescript { "x-request": { service: async (params) => { // 使用自定义的axios实例发送请求 const response = await axios.get('/api/users', { params }) return response.data } } } ``` ### `customService` - **类型**: `(config: RequestConfig) => Promise<unknown>` - **必填**: 否 - **说明**: 完全自定义的请求逻辑函数,入参为 `x-request` 配置对象,返回值为请求结果。 - **示例**: ```typescript { "x-request": { customService: async (config) => { const { url, params, method } = config // 实现自定义的请求逻辑 const response = await customFetch(url, { method, params, // 添加自定义的请求处理 timeout: 5000, retries: 3 }) return response.data } } } ``` ### `debug` - **類型**: `boolean` - **默认值**: `false` - **说明**: 开启调试模式,会在控制台输出详细的请求信息 - **示例**: ```typescript { "x-request": { url: "/api/data", debug: true // 开启调试模式 } } ``` ### `onError` - **類型**: `(err: unknown) => void` - **必填**: 否 - **说明**: 错误处理函数,用于统一处理请求错误 - **示例**: ```typescript { "x-request": { url: "/api/data", onError: (error) => { // 自定义错误处理逻辑 console.error('请求失败:', error) message.error('数据加载失败,请重试') } } } ``` ### `staticParams` - **类型**: `Record<string, any>` - **必填**: 否 - **说明**: 静态请求参数,不会被动态参数覆盖,通常用于设置固定的查询条件 - **示例**: ```typescript { "x-request": { url: "/api/products", staticParams: { category: "electronics" // 固定查询电子产品类别 }, params: { keyword: "{{ $self.value }}" // 动态搜索关键词 } } } ``` :::warning staticParams 字段已被标记为废弃,后续版本不再支持。如需设置静态参数,可以使用 `params` 字段。 ::: ## 字段方法 ### `updateRequest` formily-request 内部通过 [inject](https://core.formilyjs.org/zh-CN/api/models/field#inject) 方法注入了 updateRequest 方法,这样就可以在 schema 表达式中使用 `$self.invoke('updateRequest', request => request.params.xxx)` 来更新请求配置。 `invoke` 参数说明: - `updateRequest`: 方法为 formily-request 内部注册的自定义方法; - `(request) => void`:函数的 `request` 参数是一个 observable 对象,修改 request 会触发接口请求。 示例,在搜索框输入时,动态更新请求参数: ```json { "ready_select": { "type": "string", "x-component": "Select", "x-component-props": { "onSearch": "{{ keyword => $self.invoke('updateRequest', xrequest => xrequest.params.text = keyword) }}" }, "x-request": { "url": "/api/search", "params": { "text": "" }, // updateRequest第2个参数为函数,函数的参数为当前请求配置 "ready": "{{ !!$values.visible }}", "format": "{{ (res) => res?.data?.list || [] }}" } } } ``` 具体示例参考:[Ready](/demo/basic#ready) ### `reloadRequest` - **类型**: `() => Promise<void>` - **必填**: 否 - **说明**: 主动触发请求的方法,使用当前的请求参数重新获取数据。与 `updateRequest` 的区别在于它不需要传入回调函数来修改请求参数。 - **示例**: ```typescript { "x-component": "Select", "x-component-props": { "onVisibleChange": "{{ visible => visible && $self.invoke('reloadRequest') }}" // 展开下拉框时刷新数据 }, "x-request": { "url": "/api/options", "params": { "type": "user" }, "mountLoad": false // 禁用挂载后请求 } } ``` 以下场景特别适合使用 `reloadRequest`- 下拉框展开时刷新选项数据 - 用户手动触发数据刷新 - 需要定时更新数据