发布于 2026-01-06 2 阅读
0

我如何使用 Medusa 和 Ionic 创建电子商务应用程序

我如何使用 Medusa 和 Ionic 创建电子商务应用程序

介绍

Ionic是一款开源工具包,允许开发者创建支持多种移动平台(包括 Android 和 iOS)的跨平台应用程序。开发者可以使用他们选择的前端框架进行构建,例如 Angular、Vue 和 React。

Medusa是一个开源的可组合式电子商务平台,允许开发者创建可定制、可扩展的在线商店。Medusa 旨在为开发者提供卓越的体验,帮助他们打造独一无二的电商网站。

在本教程中,您将使用 Medusa 和 Ionic 构建一个电子商务应用程序。该应用程序可以在 Android、iOS 和 Windows 手机等移动设备上使用,也可以作为渐进式 Web 应用程序 (PWA) 使用。

您可以在GitHub 上的这个仓库中查看本教程的源代码

您将构建的 Ionic 应用程序

先决条件

要使用 Medusa,您的计算机上需要安装 Node.js(版本 14 或更高版本)。您可以从Node.js官方网站下载

设置美杜莎服务器

首先,在终端中运行以下命令来安装 Medusa CLI:

npm install -g @medusajs/medusa-cli
Enter fullscreen mode Exit fullscreen mode

接下来,运行以下命令创建新的 Medusa 服务器:

medusa new ecommerce-store-server --seed
Enter fullscreen mode Exit fullscreen mode

--seed标志会将演示数据填充到数据库中,这些数据随后可用于电子商务商店。

最后,导航到该ecommerce-store-server目录并启动服务器:

cd ecommerce-store-server
medusa develop
Enter fullscreen mode Exit fullscreen mode

如果服务器运行成功,您应该会在终端中看到类似这样的输出:

美杜莎服务器控制台输出

安装 Medusa Admin

接下来,需要设置并运行 Medusa 管理后台。请在另一个目录中运行以下命令:

git clone https://github.com/medusajs/admin medusa-admin
Enter fullscreen mode Exit fullscreen mode

进入新创建的medusa-admin目录,并安装项目所需的依赖项:

cd medusa-admin
npm install
Enter fullscreen mode Exit fullscreen mode

然后,要运行管理员程序,请在终端中执行以下命令:

npm run develop
Enter fullscreen mode Exit fullscreen mode

这将运行 Medusa 管理程序localhost:7000。请确保 Medusa 服务器也仍在运行。

打开 Medusa 管理后台后,应该会看到登录页面。

美杜莎管理员登录界面

由于您在上一节中使用了标志创建了一个 Medusa 服务器--seed,因此除了演示数据之外,还创建了一个测试用户。您可以使用该用户的电子邮件地址admin@medusa-test.com和密码supersecret登录。

Medusa 管理后台包含许多功能,例如查看订单、管理产品、配置商店和地区等等!

您可以尝试在 Medusa 管理后台编辑一些现有的演示产品或添加新产品。

在 Medusa Admin 中编辑产品元数据

初始化 Ionic 项目

在本节中,您将开始构建 Ionic 应用。

首先,运行以下命令安装 Ionic CLI:

npm install -g @ionic/cli
Enter fullscreen mode Exit fullscreen mode

然后,在另一个目录中,使用以下命令创建一个新的 Ionic 应用:

ionic start ecommerce-store blank --type=react
Enter fullscreen mode Exit fullscreen mode

本教程使用 React 创建 Ionic 应用。这已在上面的命令中使用--type标志指定。

通常需要几分钟时间来安装项目所需的所有依赖项。

安装完成后,切换到该ecommerce-store目录并安装其他所需的依赖项:

cd ecommerce-store
npm install axios
Enter fullscreen mode Exit fullscreen mode

axios用于向 Medusa 服务器发送异步请求。这将允许您执行诸如获取产品之类的操作。

测试 Ionic 应用

要测试空白的 Ionic 应用,请在终端中运行以下命令:

ionic serve --lab
Enter fullscreen mode Exit fullscreen mode

这台机器上运行着 Ionic 开发服务器localhost:8100和 Ionic Lab localhost:8200。您可以使用 Ionic Lab 来模拟应用程序在不同设备(例如 iOS 或 Android)上的外观。

Ionic Lab

更改存储 CORS 变量

由于 Ionic 应用运行在 8100 端口,您需要将 Medusa 服务器上的 Store CORS 设置更新medusa-config.js到以下文件中:

const STORE_CORS = process.env.STORE_CORS || "http://localhost:8100"
Enter fullscreen mode Exit fullscreen mode

更多信息,请查看这篇关于更新 CORS 设置的官方指南。

更改完成后,请务必重启美杜莎服务器。

创建产品卡片

在本节中,您将创建一个可重用的组件,用于在首页上以卡片形式显示产品。

首先,您需要创建两个界面,一个用于产品,另一个用于图片。这些界面将用于定义产品和图片的结构。

为此,请创建src/Interfaces.tsx包含以下内容的文件:

export interface Product {
    id: string;
    title: string;
    handle: string;
    images: Image[];
    description: string;
    variants: any[];
}

export interface Image {
    url: string;
}
Enter fullscreen mode Exit fullscreen mode

接下来,您将创建可重复使用的产品项目卡片组件。

现在接口已经定义并导出,是时候创建产品项目卡片的用户界面了。

创建一个新文件src/components/ProductItemCard/ProductItemCard.tsx,内容如下:

import React, { useEffect } from 'react';
import { IonCard, IonCardHeader, IonCardSubtitle, IonImg, IonCardTitle } from '@ionic/react';
import { Product } from '../../Interfaces';

const ProductItemCard = ({ product }: { product: Product }) => {

  return (
    <div>
      {product && (
        <IonCard routerLink={"/product/" + product["id"]} className="product_card">
          <IonImg src={product.images[0]["url"]} class="image" />
          <IonCardHeader>
            <IonCardTitle className="product_title"><b>{product["title"]}</b></IonCardTitle>
            <IonCardSubtitle>{product["handle"]}</IonCardSubtitle>
            <IonCardSubtitle>${product["variants"][0]["prices"][1]["amount"] / 100}</IonCardSubtitle>
          </IonCardHeader>
        </IonCard>
      )}
    </div>

  );
};

export default ProductItemCard;
Enter fullscreen mode Exit fullscreen mode

每张卡片都会显示产品的图片、标题、类型和价格。产品属性会传递给组件,然后显示其对应的元数据。接口Product用于强制指定product属性的类型。

创建主布局

现在单个产品卡片的组件已经创建完成,接下来需要在首页布局屏幕中获取并渲染产品。

初始化 Ionic 项目时,默认情况下会创建`.js` 和` Home.tsx.js`文件。创建一个新目录,并将 `.js` 和 `.js` 文件移动目录中。Home.csssrc/pagessrc/pages/HomeHome.tsxHome.csssrc/pages/Home

编辑页眉

打开src/pages/Home/Home.tsx文件并查看返回的 JSX 代码,你会发现系统已自动添加了一个头部信息。你可以将组件中嵌套的文本替换IonTitle为你电商网站的名称。例如:

<IonHeader>
    <IonToolbar>
      <IonTitle>Medusa Ecommerce Store</IonTitle>
    </IonToolbar>
</IonHeader>
Enter fullscreen mode Exit fullscreen mode

从美杜莎服务器获取产品

src/server-url.js创建包含以下内容的文件:

const medusaServerBaseURL = "http://localhost:9000";

export default medusaServerBaseURL;
Enter fullscreen mode Exit fullscreen mode

最好在一个文件中定义 Medusa 服务器的基本 URL。这样,如果需要更新端口或 URL,只需更新此文件中的 URL 即可。

如果您在移动设备上进行测试,则应将 URL 更改为您设备的 IP 地址。

接下来,在文件中src/pages/Home/Home.tsx,将文件开头的导入语句替换为以下内容:

import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonGrid, IonRow, IonCol, } from '@ionic/react';
import './Home.css';
import React, { useEffect, useState } from 'react';
import axios from "axios";
import ProductItemCard from '../../components/ProductItemCard/ProductItemCard';
import medusaServerBaseURL from "../../server-url";
Enter fullscreen mode Exit fullscreen mode

然后,在组件内部创建一个状态变量Home来存储产品:

const [products, setProducts] = useState([]);
Enter fullscreen mode Exit fullscreen mode

创建状态变量后,添加以下内容:

useEffect(() => {
    axios
      .get(`${medusaServerBaseURL}/store/products`)
      .then((response) => {

        if (response.data) {
          let products = response.data.products;

          setProducts(products);
        }
      })
      .catch((err) => {
        console.log("error", err)
      });
  }, []);
Enter fullscreen mode Exit fullscreen mode

使用该方法useEffect,Home 组件会在屏幕首次打开时从服务器获取产品信息。它会axiosList Products端点发送请求。然后,请求结果将用于设置products状态变量。

创建产品网格

接下来,我们需要使用该<IonGrid>组件创建产品项网格。

仍然在 ` <head>` 标签内src/pages/Home/Home.tsx,将以下内容添加到<IonContent>返回的 JSX 元素中,替换原有<ExploreContainer>组件:

<IonGrid class="ion-no-padding ion-no-margin">
    <IonRow>
     {products.map((product, i) =>
         <IonCol size="6">
             <ProductItemCard product={product} />
         </IonCol>)}
     </IonRow>
</IonGrid>
Enter fullscreen mode Exit fullscreen mode

此网格使用组件渲染每个产品ProductItemCard。默认情况下每行显示两个产品,但如果您想将其更改为每行显示一个产品,请将元素size的 prop更新为 `<product> `。有关 Ionic 网格的更多信息,请务必查看官方文档IonCol12

添加 CSS

修改内容src/pages/Home/Home.css以添加一些有用的样式:

.product_card {
    cursor: pointer;
}

.product_title {
    font-size: 1em;
}
Enter fullscreen mode Exit fullscreen mode

测试主屏幕

请确保 Medusa 服务器仍在运行,如果 Ionic 服务器未运行,请重新运行 Ionic 服务器。

如果您现在在 Ionic lab 中打开该应用程序,您应该会在主屏幕上看到从 Medusa 服务器获取的产品。

请注意,由于系统设置,所示屏幕截图为深色模式。如果您使用浅色模式,屏幕显示效果会有所不同。

应用程序的主屏幕,以网格形式列出产品

创建产品详情屏幕

在本节中,您将创建ProductDetail屏幕。该屏幕将显示各个产品的信息和图片。

src/pages/ProductDetailPage/ProductDetailPage.tsx创建包含以下内容的文件:

import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
import './ProductDetailPage.css';
import React, { useEffect, useState } from 'react';
import { IonCard, IonCardHeader, IonBackButton, IonButtons, IonCardSubtitle, IonToast, IonImg, IonCardTitle, IonCardContent, IonButton } from '@ionic/react';
import axios from "axios";
import { RouteComponentProps } from 'react-router-dom';
import { Product } from '../../Interfaces';
import medusaServerBaseURL from "../../server-url";

const ProductDetailPage: React.FC<RouteComponentProps<{ id: string }>> = (props) => {
  const [product, setProduct] = useState<Product>();

  useEffect(() => {
    let product_id = props.match.params.id;

    axios
      .get(`${medusaServerBaseURL}/store/products/${product_id}`)
      .then((response) => {
        if (response.data.product) {
          setProduct(response.data.product);
        }
      })
      .catch((err) => {
        console.log("error", err)
      });
  }, [props.match.params.id])

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonBackButton text="">
            </IonBackButton>
          </IonButtons>
          <IonTitle>Medusa Ecommerce Store</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>

        {product && (

          <IonCard mode="ios">
            {product["images"] && (
              <IonImg class="product_detail_img" src={product.images[0]["url"]} />
            )}
            <IonCardHeader>
              <div className="metaInfo">
                <IonCardTitle>{product["title"]}</IonCardTitle>
                <IonCardSubtitle>{product["handle"]}</IonCardSubtitle>
                <h3>${product["variants"][0]["prices"][1]["amount"] / 100}</h3>
              </div>

            </IonCardHeader>
            <IonCardContent>
              <h3>Description</h3>
              {product["description"]}
              <IonButton class="button" size="default" shape="round" expand="block">Add to Cart</IonButton>

            </IonCardContent>
          </IonCard>
        )}

      </IonContent>
    </IonPage>
  );
};

export default ProductDetailPage;
Enter fullscreen mode Exit fullscreen mode

本页面首先从路由参数中获取产品 ID。然后,axios使用该库向 Medusa 服务器上的“检索产品”product端点发送请求,以获取单个产品的数据。最后,根据请求的响应设置状态变量。

src/pages/ProductDetailPage/ProductDetailPage.css接下来,创建包含以下内容的文件:

.product_detail_img {
    height: 30vh;
    object-fit: cover;
}

@media (prefers-color-scheme: light) {  
    h3 {   
         color: black;  
    }
}

h3 {
    font-weight: bold;
}

.button {
    margin-top: 1em;
}

.metaInfo {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
}
Enter fullscreen mode Exit fullscreen mode

添加新路线

要真正使用新屏幕,必须将其作为新路由添加到应用程序中。

首先,导入ProductDetailPage组件src/App.tsx

import ProductDetailPage from './pages/ProductDetailPage/ProductDetailPage';
Enter fullscreen mode Exit fullscreen mode

然后,将新路由添加到已定义的路由列表中App

const App: React.FC = () => (
  <IonApp>
    <IonReactRouter>
      <IonRouterOutlet>
        <Route exact path="/home">
          <Home />
        </Route>
        <Route exact path="/">
          <Redirect to="/home" />
        </Route>
        <Route path="/product/:id/" component={ProductDetailPage} />

      </IonRouterOutlet>
    </IonReactRouter>
  </IonApp>
);
Enter fullscreen mode Exit fullscreen mode

测试产品详情屏幕

在 Medusa 和 Ionic 开发服务器仍在运行的情况下,请在浏览器中打开 Ionic Lab,然后点击主屏幕上的某个产品。此时会打开一个新页面,显示该产品的详细信息。

测试产品详情页面

显示添加到购物车通知

在本节中,您将添加一个简单的弹出式通知,当点击“添加到购物车”按钮时会显示该通知。这实际上并不会将商品添加到购物车,而只是模拟该功能。

src/pages/ProductDetailPage/ProductDetailPage.tsx文件中,在创建product状态变量之后添加以下内容,以创建一个新的状态变量来管理 Toast 通知的可见性:

const [showToast, setShowToast] = useState(false);
Enter fullscreen mode Exit fullscreen mode

然后,IonToast在返回的 JSX 中添加一个组件。它应该放置在组件内部IonContent和之后IonCard

<IonContent fullscreen>
   {product && (

     <IonCard mode="ios">
            ...
     </IonCard>
    )}

    <IonToast
      isOpen={showToast}
      onDidDismiss={() => setShowToast(false)}
      message="Product added to cart"
      duration={800}
    />

</IonContent>
Enter fullscreen mode Exit fullscreen mode

最后,修改“添加到购物车”按钮,添加onClick事件处理程序:

<IonButton class="button" size="default" shape="round" expand="block"  
onClick={() => setShowToast(true)}>Add to Cart</IonButton>
Enter fullscreen mode Exit fullscreen mode

现在,每当点击按钮时,该值showToast都会被设置为true显示 toast 通知。

测试通知

在 Medusa 和 Ionic 开发服务器仍在运行的情况下,在其中一个产品的详情页面点击“添加到购物车”按钮。随后会显示一个提示信息,持续几秒钟,表明该产品已添加到购物车。

测试商品添加到购物车时的通知功能

接下来是什么?

通过按照本教程操作,您已成功将 Ionic 应用连接到 Medusa 服务器,并从服务器获取了产品。

您可以使用 Medusa 服务器在 Ionic 应用中添加更多功能,包括:

如果您对 Medusa 有任何疑问或问题,请随时通过Discord联系 Medusa 团队 

文章来源:https://dev.to/medusajs/how-i-created-an-ecommerce-app-with-medusa-and-ionic-2lkg