Skip to content

能否出一个useRequest的组件用法? #272

@Preyou

Description

@Preyou

Description

用起来类似这样

    <use-request
      :service="() => $api.general.get_v1_quick_tasks({ params: { current_page: 1, page_size: 10, query: '', user_id: user.id } })"
    >
      <template #default="{ data }">
        {{ data }}
      </template>
    </use-request>

Suggested solution

我有了一版实现,但是ts类型有些问题,不知道怎么解决

<script setup lang="ts" generic="TData, TParams extends unknown[], PluginsOptions extends UseRequestPlugin<TData, TParams>[], SR extends unknown = unknown">
import type {
  UseRequestOptions,
  UseRequestOptionsWithFormatResult,
  UseRequestOptionsWithInitialData,
  UseRequestPlugin,
  useRequestResult,
  UseRequestService,
} from 'vue-hooks-plus/es/useRequest/types'
import { computed } from 'vue'
import { useRequest } from 'vue-hooks-plus'

/**
 * UseRequestAction组件 - 将useRequest hook封装为组件形式
 *
 * @description
 * 该组件将vue-hooks-plus的useRequest hook封装为组件形式,支持所有useRequest的功能和重载形式。
 * 通过作用域插槽将请求状态和方法传递给子组件。
 */
type PluginsMiddleOptionsType<PluginsOptions, TData, TParams extends unknown[] = unknown[]> = PluginsOptions extends (infer P)[]
  ? P extends UseRequestPlugin<TData, TParams, infer R>
    ? R
    : never
  : never

// 工具类型:检查选项中是否包含特定属性
type HasOption<O, K extends string> = O extends { [key in K]: unknown } ? true : false

// 工具类型:获取选项的类型
type GetOptionType<O, K extends string> = O extends { [key in K]: infer T } ? T : never

// 定义Props类型
type Props = {
  /** 请求服务函数(带格式化结果和初始数据) */
  service: UseRequestService<SR, TParams>
  options?: UseRequestOptionsWithFormatResult<TData, TParams, PluginsMiddleOptionsType<PluginsOptions, TData, TParams>, SR> &
    UseRequestOptionsWithInitialData<TData, TParams, PluginsMiddleOptionsType<PluginsOptions, TData, TParams>>
  plugins?: PluginsOptions
} | {
  /** 请求服务函数(带格式化结果) */
  service: UseRequestService<SR, TParams>
  options?: UseRequestOptionsWithFormatResult<TData, TParams, PluginsMiddleOptionsType<PluginsOptions, TData, TParams>, SR>
  plugins?: PluginsOptions
} | {
  /** 请求服务函数(带初始数据) */
  service: UseRequestService<TData, TParams>
  options?: UseRequestOptionsWithInitialData<TData, TParams, PluginsMiddleOptionsType<PluginsOptions, TData, TParams>>
  plugins?: PluginsOptions
} | {
  /** 请求服务函数(基础形式) */
  service: UseRequestService<TData, TParams>
  options?: UseRequestOptions<TData, TParams, PluginsMiddleOptionsType<PluginsOptions, TData, TParams>>
  plugins?: PluginsOptions
}

// 定义默认插槽的类型
type SlotProps = useRequestResult<
  TData,
  TParams,
  HasOption<NonNullable<typeof props.options>, 'formatResult'> extends true
    ? GetOptionType<NonNullable<typeof props.options>, 'formatResult'>
    : false,
  HasOption<NonNullable<typeof props.options>, 'initialData'> extends true
    ? GetOptionType<NonNullable<typeof props.options>, 'initialData'>
    : false
>

const props = defineProps<Props>()

defineSlots<{
  default: (props: SlotProps) => unknown
}>()
const defaultOptions = {} as const
const defaultPlugins = [] as const

const options = computed(() => props.options || defaultOptions)
const plugins = computed(() => props.plugins || defaultPlugins)

// 调用useRequest并获取结果
const result = useRequest<TData, TParams, PluginsOptions, SR>(
  // @ts-expect-error 这里的类型可以忽略
  props.service,
  options.value,
  plugins.value,
)
</script>

<template>
  <slot v-bind="result" />
</template>

Alternative

No response

Additional context

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    todoThings to do

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions