Vue Storefront项目扩展开发指南:添加自定义API方法
前言
在Vue Storefront项目中,统一数据模型(Unified Data Model)已经包含了电商后端最常用的数据。但在实际开发中,我们经常需要扩展功能,比如添加社交媒体图片展示等特性。本文将详细介绍如何在Vue Storefront项目中添加自定义API扩展。
扩展方案选择
当需要扩展功能时,我们有两种主要选择:
- 扩展现有集成:在已有集成基础上添加新的API方法
- 自定义集成:完全从头开始创建新的集成
对于大多数场景,第一种方案更为合适,特别是当只需要添加少量特定功能时。本文将重点介绍第一种方案。
实战案例:社交媒体图片功能
我们将实现一个"社交媒体产品图片"功能,展示产品在社交媒体上的相关图片。为简化示例,我们使用Lorem Picsum API模拟社交媒体图片数据。
第一步:创建API方法
- 定义类型:在
/api/socialImagesExtension/types.ts
中定义请求参数和响应类型
export interface SocialImagesArgs {
seed: string; // 使用产品ID作为种子值
}
export interface SocialImagesResponse {
id: string;
author: string;
width: number;
height: number;
url: string;
download_url: string;
}
- 实现API方法:在
/api/socialImagesExtension/getImages.ts
中实现具体逻辑
import { SapccIntegrationContext } from "@vsf-enterprise/sapcc-api";
import { SocialImagesArgs, SocialImagesResponse } from "./types";
export async function getSocialImages(
context: SapccIntegrationContext,
args: SocialImagesArgs,
): Promise<SocialImagesResponse> {
const image: SocialImagesResponse = await (
await fetch(`https://picsum.photos/seed/${args.seed}/info`)
).json();
return image;
}
- 导出方法:在
/api/socialImagesExtension/index.ts
中导出
export * from "./getImages";
第二步:创建中间件扩展
- 定义扩展:在
integrations/sapcc/extensions/socialImagesExtension.ts
中创建扩展
import type { ApiClientExtension } from "@vue-storefront/middleware";
import { getSocialImages } from "../../../api/socialImagesExtension";
export const socialImagesExtension = {
name: "socialImagesExtension",
extendApiMethods: {
getSocialImages,
},
} satisfies ApiClientExtension;
- 导出扩展:更新
/integrations/sapcc/extensions/index.ts
export * from "./unified";
export * from "./multistore";
export * from "./socialImagesExtension";
第三步:类型导出
- 导出端点类型:更新
integrations/sapcc/types.ts
import { WithoutContext } from "@vue-storefront/middleware";
import { socialImagesExtension } from "./extensions";
export type SocialImagesExtension = typeof socialImagesExtension;
export type SocialImagesExtensionEndpoints = WithoutContext<SocialImagesExtension["extendApiMethods"]>;
第四步:注册扩展
更新integrations/sapcc/config.ts
配置文件:
import { socialImagesExtension } from "./extensions";
export const config = {
// ...其他配置
extensions: (extensions: ApiClientExtension[]) => [
...extensions,
unifiedApiExtension,
...(IS_MULTISTORE_ENABLED ? [multistoreExtension] : []),
socialImagesExtension,
],
} satisfies Integration<MiddlewareConfig>;
第五步:导出类型
更新types.ts
文件,确保类型可用:
export {
type SocialImagesExtensionEndpoints,
type UnifiedEndpoints,
} from "./integrations/sapcc/types";
export * from "@vsf-enterprise/unified-api-sapcc/udl";
export * from "./api/socialImagesExtension/types";
第六步:配置SDK
更新SDK配置文件sdk.config.ts
:
import type { UnifiedEndpoints, SocialImagesExtensionEndpoints } from 'storefront-middleware/types';
export const { getSdk } = createSdk(options, ({ buildModule, middlewareModule, middlewareUrl, getRequestHeaders }) => ({
unified: buildModule(middlewareModule<UnifiedEndpoints>, {
apiUrl: `${middlewareUrl}/commerce`,
defaultRequestConfig: {
headers: getRequestHeaders(),
},
}),
socialImagesExtension: buildModule(middlewareModule<SocialImagesExtensionEndpoints>, {
apiUrl: `${middlewareUrl}/commerce`,
defaultRequestConfig: {
headers: getRequestHeaders(),
},
}),
}));
现在,getSocialImages
方法就可以通过SDK在项目中使用:
const { data } = sdk.socialImagesExtension.getSocialImages({ seed: productId });
第七步:实现前端组件
- 创建自定义Hook:
useSocialImages.ts
import { useQuery } from '@tanstack/react-query';
import { useSdk } from '~/sdk';
import { SocialImagesArgs } from '~/types';
export function useSocialImages(params: SocialImagesArgs) {
const sdk = useSdk();
return useQuery({
queryKey: ['social-image', params.seed],
queryFn: () => sdk.socialImagesExtension.getSocialImages(params),
refetchOnMount: false,
refetchOnWindowFocus: false,
});
}
- 创建组件:
SocialImages.tsx
import Image from 'next/image';
import { useSocialImages } from '~/hooks/useSocialImages';
export function SocialImages({ productId }: { productId: string }) {
const socialImage = useSocialImages({ seed: productId });
return (
<div className="px-4">
<Image
alt="social image"
src={socialImage.data?.download_url ?? ''}
width={socialImage.data?.width}
height={socialImage.data?.width}
unoptimized
/>
<p>By {socialImage.data?.author}</p>
</div>
);
}
- 集成到产品详情页:更新
ProductAccordion.tsx
// 在现有组件中添加
<Divider className="my-4" />
<AccordionItem
label={<h2 className="font-semibold md:typography-headline-3 typography-headline-4">Social Images</h2>}
open={isOpened('socialImages')}
onToggle={() => toggleItem('socialImages')}
>
<SocialImages productId={productId} />
</AccordionItem>
总结
通过以上步骤,我们成功地在Vue Storefront项目中添加了一个完整的自定义功能扩展。这个流程展示了从后端API到前端组件的完整开发链路,包括:
- 定义API方法和类型
- 创建中间件扩展
- 配置SDK
- 实现前端组件
这种扩展方式保持了项目的模块化和可维护性,同时提供了良好的类型支持。开发者可以根据实际需求,按照类似的模式添加各种自定义功能。
最佳实践建议
- 类型安全:始终为API方法和响应定义明确的TypeScript类型
- 模块化:将相关功能组织在独立的目录中
- 错误处理:在实际项目中添加适当的错误处理逻辑
- 性能优化:考虑添加缓存机制减少API调用
- 测试:为自定义功能编写单元测试和集成测试
通过遵循这些实践,可以确保自定义扩展的质量和可维护性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考