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

使用 Nodejs 和 Vue Vite 构建购物车

使用 Nodejs 和 Vue Vite 构建购物车

本文将介绍如何为我们的应用程序构建购物车前端。我们将使用 Vue Vite,它具有更快的热模块重载功能。

您可以查看我们用Nodejs构建的后端部分,我们已经发布了该部分。

我们需要为 Vite 创建应用程序目录。请vue-cart在桌面创建一个目录,然后运行以下命令来安装 Vite:

cd desktop
mkdir vue-cart && cd vue-cart
npm init vite-app vue-cart
Enter fullscreen mode Exit fullscreen mode

初始化 Vite 应用程序后,请在终端运行以下命令:

cd vue-cart
npm install
code . && npm run dev
Enter fullscreen mode Exit fullscreen mode

code .命令将在 Visual Studio Code 中打开项目。

接下来,我们将搭建应用程序的用户界面。您可以从WrapPixel 的 UI Kit中获取所有 UI 组件。

有些在线模板商店可以提供很棒的 UI 模板和 Vue 模板,例如WrapPixelAdminMart

让我们创建两个组件:product.vuechart.vueproduct.Vue将列出我们所有的产品,cart.vue将列出我们购物车中的所有商品。

我们需要通过在文件中添加 CDN 来将 Bootstrap 配置到我们的应用程序中index.html

我们只需要 Bootstrap CSS CDN,所以请前往 Bootstrap 官方 CDN,复制 CSS 链接并将其添加到 index.html 文件中:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vite app</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
    integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始设置组件了。首先,我们将创建根 Vue.js 文件,并为应用程序设置路由。

首先,我们运行以下命令安装 Vue 3 路由器:

 npm i --save vue-router@v4.0.0-alpha.11
Enter fullscreen mode Exit fullscreen mode

安装完成后,我们需要为应用程序设置路由。我们将设置一些基本路由来显示购物车中的商品。

router.js在目录下创建一个文件src,并添加以下代码:

import {
    createWebHistory,
    createRouter
} from "vue-router";
import Home from "./components/HelloWorld.vue";
import Product from './components/product.vue'
import Cart from './components/cart.vue'
const history = createWebHistory();
const routes = [{
    path: "/",
    component: Product
}, {
    path: "/cart",
    component: Cart
}, ];
const router = createRouter({
    history,
    routes
});
export default router;
Enter fullscreen mode Exit fullscreen mode

在这里,我们基本上是将购物车和产品组件注册为路由。

我们需要在 main.js 文件中注册路由:

import {
    createApp
} from 'vue'
import App from './App.vue'
import './index.css'
import router from "./router";

createApp(App).use(router).mount('#app')
Enter fullscreen mode Exit fullscreen mode

完成上述步骤后,我们需要将App.vue根组件更改为以下内容,以便它能够渲染所有组件:

<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-info">
    <div class="container">
      <router-link to="/" class="navbar-brand">Vue Cart </router-link>
      <button
        class="navbar-toggler"
        type="button"
        data-toggle="collapse"
        data-target="#navbarNav"
        aria-controls="navbarNav"
        aria-expanded="false"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse justify-content-end" id="navbarNav">
        <ul class="navbar-nav">
          <li class="nav-item active">
            <router-link to="/" class="nav-link">Home </router-link>
          </li>
          <li class="nav-item">
            <router-link to="/cart" class="nav-link">Cart </router-link>
          </li>
        </ul>
      </div>
    </div>
  </nav>
  <router-view />
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

现在我们可以设置产品卡片并向后端 API 发出 HTTP 请求。


赞助内容:

Vue.js


让我们为首页创建一个简单的用户界面。将以下代码添加到product.vue文件中:

<template>
  <main>
    <section>
      <div
        class="banner-innerpage"
        style="
          background-image: url(https://images.pexels.com/photos/1005638/pexels-photo-1005638.jpeg?cs=srgb&dl=pexels-oleg-magni-1005638.jpg&fm=jpg);
        "
      >
        <div class="container">
          <!-- Row  -->
          <div class="row justify-content-center">
            <!-- Column -->
            <div
              class="col-md-6 align-self-center text-center"
              data-aos="fade-down"
              data-aos-duration="1200"
            >
              <h1 class="title">Shop listing</h1>
              <h6 class="subtitle op-8">
                We are small team of creative people working together
              </h6>
            </div>
            <!-- Column -->
          </div>
        </div>
      </div>
    </section>
    <section>
      <div class="spacer">
        <div class="container">
          <div class="row mt-5">
            <div class="col-lg-9">
              <div class="row shop-listing">
                <div class="col-lg-6">
                  <div class="card shop-hover border-0">
                    <img
                      src="https://images.pexels.com/photos/1005638/pexels-photo-1005638.jpeg?cs=srgb&dl=pexels-oleg-magni-1005638.jpg&fm=jpg"
                      alt="wrapkit"
                      class="img-fluid"
                    />
                    <div class="card-img-overlay align-items-center">
                      <button class="btn btn-md btn-info">
                        Add to cart
                      </button>
                    </div>
                  </div>
                  <div class="card border-0">
                    <h6><a href="#" class="link">Mens Wear </a></h6>
                    <h6 class="subtitle">by Wisdom</h6>
                    <h5 class="font-medium m-b-30">
                      $195 / <del class="text-muted line-through">$225</del>
                    </h5>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  </main>
</template>
<style>
.banner-innerpage {
  padding: 150px 0 100px;
  background-size: cover;
  background-position: center center;
}
.banner-innerpage .title {
  color: #ffffff;
  text-transform: uppercase;
  font-weight: 700;
  font-size: 40px;
  line-height: 40px;
}
.banner-innerpage .subtitle {
  color: #ffffff;
}
.shop-listing .shop-hover {
  position: relative;
}
.shop-listing .shop-hover .card-img-overlay {
  display: none;
  background: rgba(255, 255, 255, 0.5);
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  -ms-flex-pack: center;
  justify-content: center;
}
.shop-listing .shop-hover:hover .card-img-overlay {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
.shop-listing .shop-hover .label {
  padding: 5px 10px;
  position: absolute;
  top: 10px;
  right: 10px;
}
/*******************
shop table
*******************/
.shop-table td {
  padding: 30px 0;
}
</style>
Enter fullscreen mode Exit fullscreen mode

这将为我们的应用程序创建一个简单的用户界面。接下来,我们需要开始使用我们的端点。启动我们在上一个教程中创建的后端 API,之后我们就可以使用 JavaScript 的 fetch 函数向后端发送请求了。

将以下脚本添加到<script>产品组件的相应部分:

<script>
export default {
  data() {
    return {
      products: [],
    };
  },
  created() {
    this.getProducts();
  },
  methods: {
    async getProducts() {
      const res = await fetch("http://localhost:4000/product");
      const data = await res.json();
      this.products = new Proxy(data.data, {});
      console.log(this.products);
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

这将向我们的后端 API 发出请求,获取所有产品的列表,并将产品存储在
数据实例中定义的 products 数组中。

v-for现在,我们可以通过修改包含产品卡片的列,使用 Vuejs 指令遍历我们的产品:

     <div
          class="col-lg-4"
          v-for="product in products"
          :key="product._id"
          >
          <div class="card shop-hover border-0">
          <img
          :src="'http://localhost:4000/' + product.image"
          alt="wrapkit"
          class="img-fluid"
          />
            <div class="card-img-overlay align-items-center">
             <button class="btn btn-md btn-info">
                Add to Cart
             </button>
            </div>
          </div>
          <div class="card border-0">
             <h6>
                <a href="#" class="link">{{ product.name }} </a>
             </h6>
             <h6 class="subtitle">by Wisdom</h6>
             <h5 class="font-medium m-b-30">
                $195 / <del class="text-muted line-through">$225</del>
             </h5>
          </div>
     </div>
Enter fullscreen mode Exit fullscreen mode

这将列出我们数据库中存储的所有产品。

店铺列表

现在我们来添加这个add to cart功能。我们将创建一个方法,该方法接收产品 ID 和默认数量作为参数,然后将其发送到后端。

让我们来定义一下我们的addToCart方法:

 async addToCart(id, quantity) {
      try {
        const response = await fetch("http://localhost:4000/cart", {
          method: "POST",
          body: JSON.stringify({
            productId: id,
            quantity: quantity,
          }),
          headers: {
            "Content-type": "application/json; charset=UTF-8",
          },
        });
        let data = await response.json();
        alert("Item added to cart");
        console.log(data);
      } catch (err) {
        alert("Something went wrong");
        console.log(err);
      }
    },
Enter fullscreen mode Exit fullscreen mode

完成这些步骤后,我们需要为按钮添加点击事件,以触发该方法:

 <button
    class="btn btn-md btn-info"
    @click="addToCart(product._id, 1)"
    >
      Add to Cart
 </button>
Enter fullscreen mode Exit fullscreen mode

这里我们传递产品 ID,默认数量为 1。

现在我们可以开始着手处理购物车商品的查看、购物车商品的递增和购物车商品的清空等功能了。

让我们转到cart.vue组件并构建用户界面:

<template>
  <main>
    <section>
      <div
        class="banner-innerpage"
        style="
          background-image: url(https://images.pexels.com/photos/1005638/pexels-photo-1005638.jpeg?cs=srgb&dl=pexels-oleg-magni-1005638.jpg&fm=jpg);
        "
      >
        <div class="container">
          <!-- Row  -->
          <div class="row justify-content-center">
            <!-- Column -->
            <div
              class="col-md-6 align-self-center text-center"
              data-aos="fade-down"
              data-aos-duration="1200"
            >
              <h1 class="title">Cart</h1>
              <h6 class="subtitle op-8">
                We are small team of creative people working together.
              </h6>
            </div>
            <!-- Column -->
          </div>
        </div>
      </div>
    </section>
    <section>
      <div class="spacer">
        <div class="container">
          <div class="row mt-5">
            <div class="col-lg-9">
              <div class="row shop-listing">
                <table class="table shop-table">
                  <tr>
                    <th class="b-0">Image</th>
                    <th class="b-0">Name</th>
                    <th class="b-0">Price</th>
                    <th class="b-0">Quantity</th>
                    <th class="b-0 text-right">Total Price</th>
                  </tr>
                  <tr>
                    <td>
                      <img
                        src="../assets/images/innerpage/shop/1.jpg"
                        width="200"
                        alt="wrapkit"
                      />
                    </td>
                    <td>
                      Mens Wear
                    </td>
                    <td>
                      $3000
                    </td>
                    <td>
                      <button class="btn btn-primary btn-sm">+</button> 3
                      <button class="btn btn-primary btn-sm">
                        -
                      </button>
                    </td>
                    <td class="text-right">
                      <h5 class="font-medium m-b-30">
                        $195
                      </h5>
                    </td>
                  </tr>
                  <tr>
                    <td colspan="4" align="right">Subtotal :$1000</td>
<td colspan="4" align="right">
                      <button class="btn btn-danger">Empty Cart</button>
                    </td>
                  </tr>

                </table>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  </main>
</template>
Enter fullscreen mode Exit fullscreen mode

这将为我们带来如下简单的用户界面:

购物车

让我们通过创建一个方法来获取购物车中的所有商品,该方法可以从后端获取所有商品:

<script>
export default {
  data() {
    return {
      carts: {},
    };
  },
  methods: {
    async getCartItems() {
      try {
        const res = await fetch("http://localhost:4000/cart");
        const data = await res.json();
        this.carts = new Proxy(data.data, {});
        console.log(this.carts);
      } catch (err) {
        console.log(err);
      }
    },
  },
  created() {
    this.getCartItems();
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

现在,我们可以通过修改表格来遍历购物车中的商品:

              <table class="table shop-table">
                      <tr>
                        <th class="b-0">Name</th>
                        <th class="b-0">Price</th>
                        <th class="b-0">Quantity</th>
                        <th class="b-0 text-right">Total Price</th>
                      </tr>
                      <tr v-for="(item, id) in carts.items" :key="id">
                        <td>{{ item.productId.name }}</td>
                        <td>{{ item.productId.price }}</td>
                        <td>
                          <button
                            class="btn btn-primary btn-sm"
                            @click="increaseQty(item.productId._id)"
                          >+</button>
                          {{ item.quantity }}
                          <button
                            class="btn btn-primary btn-sm"
                          >-</button>
                        </td>
                        <td class="text-right">
                          <h5 class="font-medium m-b-30">{{ item.total }}</h5>
                        </td>
                      </tr>
                      <tr>
                        <td colspan="3" align="right">Subtotal :{{ carts.subTotal }}</td>
                        <td colspan="4" align="right">
                          <button class="btn btn-danger">Empty Cart</button>
                        </td>
                      </tr>
                    </table>
Enter fullscreen mode Exit fullscreen mode

现在我们可以通过添加一个递增购物车商品数量的方法来实现购物车商品数量的递增:

    async increaseQty(id) {
      try {
        const res = await fetch("http://localhost:4000/cart", {
          method: "POST",
          body: JSON.stringify({
            productId: id,
            quantity: 1,
          }),
          headers: {
            "Content-type": "application/json; charset=UTF-8",
          },
        });
        this.getCartItems();
        alert("Item Increamented");
      } catch (err) {
        console.log(err);
      }
    },
Enter fullscreen mode Exit fullscreen mode

然后添加一个点击事件来监听这个方法:

<button
   class="btn btn-primary btn-sm"                          
   @click="increaseQty(item.productId._id)"
   >+
</button>
Enter fullscreen mode Exit fullscreen mode

点击按钮+将增加商品数量并更新价格。

让我们来实现清空购物车功能。该功能会清空购物车,然后将我们重定向到产品列表页面。创建一个方法来实现此功能:

  async emptyCart() {
      try {
        const res = await fetch("http://localhost:4000/cart/empty-cart", {
          method: "DELETE",
        });
        const data = await res.json();
        this.$router.push({
          path: "/",
        });
      } catch (err) {
        console.log(err);
      }
    },
Enter fullscreen mode Exit fullscreen mode

然后我们添加一个事件监听器来监听这个方法:

<button class="btn btn-danger" @click="emptyCart">Empty cart</button>
Enter fullscreen mode Exit fullscreen mode

锻炼

  • 实现递减功能
  • 移除购物车中的商品

完成之后,将你的代码推送到 Git,并在评论区添加链接。一起来玩吧😁

文章来源:https://dev.to/suniljoshi19/build-a-shopping-cart-in-nodejs-and-vue-vite-47go