实现效果

首页

在这里插入图片描述

分类页面

在这里插入图片描述

购物车

在这里插入图片描述

用户中心

在这里插入图片描述

项目说明

利用vue2+vant模仿京东app商城,实现首页商品分类页面购物车简易商品详情页登录页

创建项目

一、创建vue项目、安装模块

①、创建vue2项目mobile

$ vue create "mobile"

②、安装路由模块,vant组件

$ npm i vue-router@3 vant@latest-v2 -S

二、创建路由,创建页面组件、引入vant与样式

①、在src目录下创建views文件夹,存放页面组件
views结构如图
在这里插入图片描述
②、在src目录下创建router文件夹,新建index.js文件

import Vue from "vue";
import VueRouter from "vue-router"

Vue.use(VueRouter);

import Login from "../views/Login/index"

const routes = [
    {
        path: "/",
        redirect: "/login"
    },
    {
        name: "login",
        path: "/login",
        component: Login,
        meta: {
            title: "登录"
        }
    },
    {
        name: "main",
        path: "/main",
        component: () => import("../views/Main/index"),
        redirect: "/main/home",
        children: [
            {
                name: "home",
                path: "home",
                component: () => import("../views/Home/index"),
                meta: {
                    title: "商城首页"
                }
            },
            {
                name: "cates",
                path: "cates",
                component: () => import("../views/Cates/index"),
                meta: {
                    title: "商品分类"
                },
                children: [
                    {
                        name: "list",
                        path: "list",
                        component: () => import("../views/Cates/catelist"),
                    },
                ]
            },
            {
                name: "scar",
                path: "scar",
                component: () => import("../views/ShopCar/index"),
                meta: {
                    title: "购物车"
                }
            },
            {
                name: "mine",
                path: "mine",
                component: () => import("../views/Mine/index"),
                meta: {
                    title: "我的"
                }
            },
            {
                name: "goodsdetail",
                path: "goodsdetail",
                component: () => import("../views/Goods/index"),
                meta: {
                    title: "商品详情"
                }
            },
        ]
    }
]
const router = new VueRouter({
    mode: "history",
    linkActiveClass: "active",
    routes,

})
// 全局前置守卫
router.beforeEach((to, from, next) => {
    console.log(to, from)
    next()
})

export default router;

③、在src目录下创建utils文件夹,新建vant.js文件

import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);

④、main.js中引入vant,注册路由

import Vue from 'vue'
import App from './App.vue'
// 引入vant
import "./utils/vant"
// 引入路由模块
import router from "./router/index"


Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

三、编写页面

①、App.vue一级路由

<template>
  <div id="app">
    <div class="content">
      <router-view />
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
};
</script>

<style>
#app,
html,
body {
  width: 100%;
  height: 100%;
}
</style>

②、Login文件夹下index.vue登录页面

<template>
  <div class="box">
    <!-- 导航头 -->
    <navbar></navbar>
    <van-form @submit="onSubmit">
      <van-field
        v-model="username"
        name="username"
        placeholder="账号名/邮箱/手机号"
        :rules="[{ required: true, message: '账号名/邮箱/手机号' }]"
      />
      <van-field
        v-model="password"
        type="password"
        name="password"
        placeholder="请输入密码"
        :rules="[{ required: true, message: '请填写密码' }]"
      ></van-field>
      <div style="margin: 16px">
        <van-button round block type="danger" native-type="submit"
          >登录</van-button
        >
      </div>
      <img src="@/assets/img/login/d.png" alt="" width="150px" />
    </van-form>
  </div>
</template>

<script>
import navbar from "@/components/navbar.vue";
import { Toast } from "vant";
export default {
  data() {
    return {
      username: "",
      password: "",
    };
  },
  methods: {
    onSubmit(values) {
      console.log("submit", values);
      if (values.username === "douzi" && values.password === "123123") {
        this.$router.push({ name: "main" });
      } else {
        Toast.fail("密码错误");
      }
    },
  },
  components: {
    navbar,
  },
};
</script>

<style  scoped>
.van-field {
  margin-top: 20px;
  padding-left: 30px;
  font-size: 16px;
}
.van-button {
  background-image: -webkit-gradient(
    linear,
    left top,
    right top,
    color-stop(0, #fab3b3),
    color-stop(73%, #ffbcb3),
    to(#ffcaba)
  );
  border: none;
}
img {
  margin: 120px;
}
</style>

③、Main文件夹下index.vue(布局页面) (包含二级路由)

<template>
  <div class="box">
    <div class="content">
      <!-- <h2>主页页面-布局</h2> -->
      <!-- 二级路由 -->
      <router-view />
    </div>
    <van-tabbar v-model="active" route>
      <van-tabbar-item to="/main/home" icon="home-o">首页</van-tabbar-item>
      <van-tabbar-item to="/main/cates" icon="apps-o">分类</van-tabbar-item>
      <van-tabbar-item to="/main/scar" icon="shopping-cart-o"
        >购物车</van-tabbar-item
      >
      <van-tabbar-item to="/main/mine" icon="contact">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: 0,
    };
  },
};
</script>

<style scoped>
.content {
  width: 100%;
  height: 100%;
}
</style>

④、Home文件夹下index.vue(首页页面)

<template>
  <div class="box">
    <!-- <h2>首页页面</h2> -->
    <navbar></navbar>
    <div class="head">
      <!-- 输入搜索框      @focus="searchFocus" @cancel="onCancel"   -->
      <van-search
        v-model="value"
        show-action
        shape="round"
        placeholder="请输入搜索关键词"
        background="#c52519"
        @search="onSearch"
      >
        <template #label>
          <span class="search-logo">JD</span>
        </template>
        <template #action>
          <span style="color: #fff; font-size: 16px">登录</span>
        </template>
        <template #left>
          <van-icon
            name="wap-nav"
            color="#fff"
            size="25px"
            style="margin-right: 10px"
          />
        </template>
      </van-search>
    </div>
    <!-- lu轮播图-------- -->
    <div class="lunbo">
      <van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
        <van-swipe-item>
          <img src="@/assets/img/home/1.jpg" alt=""
        /></van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/img/home/2.jpg" alt=""
        /></van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/img/home/3.jpg" alt=""
        /></van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/img/home/4.jpg" alt=""
        /></van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/img/home/5.jpg" alt=""
        /></van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/img/home/6.jpg" alt=""
        /></van-swipe-item>
      </van-swipe>
    </div>
    <!-- 导航 -->
    <div class="nav">
      <van-swipe class="my-swipe1" autoplay="false" indicator-color="white">
        <van-swipe-item
          ><van-grid :column-num="5" :border="false">
            <van-grid-item
              v-for="value in navinfo"
              :key="value.id"
              :icon="value.src"
              :text="value.text"
            /> </van-grid
        ></van-swipe-item>
        <van-swipe-item
          ><van-grid :column-num="5" :border="false">
            <van-grid-item
              v-for="value in navinfo2"
              :key="value.id"
              :icon="value.src"
              :text="value.text"
            /> </van-grid
        ></van-swipe-item>
      </van-swipe>
    </div>
    <!-- 活动秒杀 -->
    <div class="active">
      <div class="more">
        <span>京东秒杀</span>
        <span>16</span>
        <!-- <span><a>00</a>:<a>00</a>:<a>00</a></span> -->
        <van-count-down :time="time">
          <template #default="timeData">
            <a class="block">{{ timeData.hours }}</a>
            <a class="colon">:</a>
            <a class="block">{{ timeData.minutes }}</a>
            <a class="colon">:</a>
            <a class="block">{{ timeData.seconds }}</a>
          </template>
        </van-count-down>
        <span>爆款轮番秒<van-icon name="arrow" /></span>
      </div>

      <van-swipe class="my-swipe3" autoplay="false" indicator-color="white">
        <van-swipe-item
          ><van-grid :column-num="5">
            <van-grid-item
              :border="false"
              v-for="value in activeinfo"
              :key="value.id"
              :icon="value.src"
              :text="value.price"
            /> </van-grid
        ></van-swipe-item>
        <van-swipe-item
          ><van-grid :column-num="5">
            <van-grid-item
              :border="false"
              v-for="value in activeinfo2"
              :key="value.id"
              :icon="value.src"
              :text="value.price"
            /> </van-grid
        ></van-swipe-item>
      </van-swipe>
    </div>
    <!-- 商品卡片 -->
    <!-- 商品卡片 -->
    <div class="card-list">
      <GoodsItem></GoodsItem>
    </div>
  </div>
</template>

<script>
import navbar from "@/components/navbar.vue";
import { Toast } from "vant";
import GoodsItem from "./goodItem.vue";
export default {
  data() {
    return {
      // 倒计时
      time: 30 * 60 * 60 * 1000,
      value: "",
      navinfo: [
        { id: 1, src: require("@/assets/img/bar/1.png"), text: "京东超市" },
        { id: 2, src: require("@/assets/img/bar/2.png"), text: "数码电器" },
        { id: 3, src: require("@/assets/img/bar/3.png"), text: "京东新百货" },
        { id: 4, src: require("@/assets/img/bar/4.png"), text: "京东生鲜" },
        { id: 5, src: require("@/assets/img/bar/5.png"), text: "京东到家" },
        { id: 6, src: require("@/assets/img/bar/6.png"), text: "充值缴费" },
        { id: 7, src: require("@/assets/img/bar/7.png"), text: "附近好店" },
        { id: 8, src: require("@/assets/img/bar/8.png"), text: "领券" },
        { id: 9, src: require("@/assets/img/bar/9.png"), text: "PLUS会员" },
        { id: 10, src: require("@/assets/img/bar/10.png"), text: "京东国际" },
      ],
      navinfo2: [
        { id: 1, src: require("@/assets/img/bar/11.png"), text: "京东拍卖" },
        { id: 2, src: require("@/assets/img/bar/12.png"), text: "玩3C" },
        { id: 3, src: require("@/assets/img/bar/13.png"), text: "沃尔玛" },
        { id: 4, src: require("@/assets/img/bar/14.png"), text: "美妆馆" },
        { id: 5, src: require("@/assets/img/bar/15.png"), text: "京东旅行" },
        { id: 6, src: require("@/assets/img/bar/16.png"), text: "拍拍二手" },
        { id: 7, src: require("@/assets/img/bar/17.png"), text: "全部" },
      ],
      // 活动秒杀
      active: 8,
      // 活动秒杀信息
      activeinfo: [
        { id: 1, src: require("@/assets/img/active/1.jpg"), price: "¥46" },
        { id: 2, src: require("@/assets/img/active/2.jpg"), price: "¥2379" },
        { id: 3, src: require("@/assets/img/active/3.jpg"), price: "¥62" },
        { id: 4, src: require("@/assets/img/active/4.jpg"), price: "¥698" },
        { id: 5, src: require("@/assets/img/active/5.jpg"), price: "¥459" },
      ],
      activeinfo2: [
        { id: 1, src: require("@/assets/img/active/6.jpg"), price: "¥248" },
        { id: 2, src: require("@/assets/img/active/7.jpg"), price: "¥1399" },
        { id: 3, src: require("@/assets/img/active/8.jpg"), price: "¥297" },
        { id: 4, src: require("@/assets/img/active/9.jpg"), price: "¥2894" },
      ],
    };
  },
  methods: {
    onSearch(val) {
      Toast(val);
    },
    onCancel() {
      Toast("取消");
    },
  },
  components: {
    GoodsItem,
    navbar,
  },
};
</script>

<style scoped>
.box {
  /* background-color: rgb(233, 233, 233); */
}
.search-logo {
  color: #e93c3e;
  font-weight: bold;
  font-size: 20px;
}
.van-search__content--round {
  width: 300px;
}
.lunbo {
  /* background: #c52519; */
  background-image: linear-gradient(0deg, #f1503b, #c82519 50%);
  border-bottom-left-radius: 100%;
  border-bottom-right-radius: 100%;
}
.my-swipe {
  margin: 0 auto 0;
  border-radius: 15px;
  width: 360px;
  height: 150px;
}
.my-swipe .van-swipe-item {
  color: #fff;
  padding: 0;
  text-align: center;
  background-color: #ffffff;
}
.my-swipe .van-swipe-item img {
  width: 100%;
  height: 100%;
}
.my-swipe1 .van-swipe-item {
  color: #fff;
  text-align: center;
  background-color: #ffffff;
}
::v-deep .van-swipe__indicator--active {
  background-color: red;
}
/* --------------------- */
.active {
  background-color: #fff;
  border-radius: 5px;
  height: 140px;
  width: 369px;
  overflow: hidden;
  margin: auto;
  border: 1px solid rgb(189, 189, 189);
}
.active .more {
  width: 100%;
  height: 35px;
  background: url("../../assets/img/active/bgccc.png") no-repeat center/cover;
  display: flex;
  justify-content: space-around;
  align-items: center;
}
.active .more span {
  display: inline-block;
  height: 18px;
  line-height: 18px;
  font-size: 12px;
  color: #333;
}
.active .more span:nth-of-type(2) {
  width: 10%;
  color: red;
  background: url("../../assets/img/active/bgc.png") no-repeat top 0 right 0 /21px
    18px;
}
/* .active > .more span:nth-of-type(3) {
  width: 40%;
  color: red;
}
.active > .more span:nth-of-type(3) a {
  display: inline-block;
  padding: 1px;
  border-radius: 5px;
  background-color: red;
  color: #fff;
  font-size: 14px;
} */
.active .more span:nth-of-type(3) {
  color: red;
}
.active .more span:nth-of-type(3) .van-icon-arrow {
  display: inline-block;
  background-color: red;
  color: white;
  border-radius: 50%;
}
.active ::v-deep .van-tabs__content {
  display: flex;
}
.active ::v-deep .van-tabs__content .van-tab__pane span {
  color: red;
}
/* ------------ogo0ds */
.card-list {
  margin: 15px auto 0;
  width: 369px;
  border-radius: 5px;
}

.van-count-down {
  width: 40%;
  height: 18px;
}
.van-count-down .colon {
  display: inline-block;
  /* margin: 0 4px; */
  color: #ee0a24;
}
.van-count-down .block {
  display: inline-block;
  width: 20px;
  color: #fff;
  border-radius: 5px;
  font-size: 12px;
  text-align: center;
  background-color: #ee0a24;
}
.my-swipe3 {
  height: 105px;
}
.my-swipe3 ::v-deep i.van-icon.van-grid-item__icon {
  font-size: 55px;
}
.my-swipe3 ::v-deep .van-grid-item__text {
  font-size: 15px;
  color: #f2270c;
  font-weight: 550;
  /* font-family: JDZhengHT-EN-Regular; */
}
.my-swipe3 .van-swipe-item {
  color: #fff;
  text-align: center;
}
</style>

⑤、Home文件夹下goodItem.vue(商品组件)

<template>
  <div class="goods-item">
    <div
      class="item"
      v-for="item in goods"
      :key="item.id"
      @click="showGood(item)"
    >
      <div class="item-detail">
        <img :src="item.src" alt="" />
        <div class="desc">
          <template><span v-if="item.status === 1">京东超市</span></template
          >{{ item.text }}
        </div>
        <div class="price">
          <span class="new-price">{{ item.price }}.00</span>
          <!-- <span class="old-price">
            <del>{{ item.GoodPriceaftersale }}</del>
          </span> -->
        </div>
        <p class="same">
          <span>{{ item.count }}条评论</span><span>看相似</span>
        </p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      goods: [
        {
          id: 1,
          src: require("@/assets/img/goods/1.webp"),
          text: "CGVS睡衣女士棉春秋季薄款套头家居服可爱少sadsadas女卡通学生居家长袖套装 YS5251 M(建议身高150-156 体重80-100)",
          price: 188,
          count: "17",
          status: 1,
        },
        {
          id: 2,
          src: require("@/assets/img/goods/2.webp"),
          text: "云米(VIOMI)1.5匹智能家电 变频冷暖Space E AI全域风 新一级以旧换新 壁挂式挂机空调KFRd-35GW/Y2QX2-A1",
          price: 4888,
          count: "18万",
        },
        {
          id: 3,
          src: require("@/assets/img/goods/3.webp"),
          text: "红毛丹罐头 泰双象 2罐 新鲜毛荔枝双象红毛丹糖水果罐头儿时记忆 红毛丹2罐",
          price: 288,
          count: "1万+",
          status: 1,
        },
        {
          id: 4,
          src: require("@/assets/img/goods/4.webp"),
          text: "海尔(Haier)冰箱 467升一级能效双变频风冷无霜十字对开门四开门多门家用超薄省电大容量电冰箱",
          price: 6999,
          count: "1000+",
        },
        {
          id: 5,
          src: require("@/assets/img/goods/5.webp"),
          text: "omto托特包女包小众单肩大容量上课通勤大包百搭手提包女 松露黑中号【底托一起发】",
          price: 2586,
          count: "50万+",
          status: 1,
        },
        {
          id: 6,
          src: require("@/assets/img/goods/6.webp"),
          text: "华凌冰箱 549升白色对开门双开门家用超薄冰箱 一级能效双变频风冷无霜WiFi智能家用大容量冰箱BCD-549WKPZH",
          price: 5999,
          count: "500+",
        },
        {
          id: 7,
          src: require("@/assets/img/goods/7.webp"),
          text: "罗技(Logitech)MX Master 3S 鼠标 无线蓝牙鼠标 办公鼠标 右手鼠标  石墨黑  带Logi Bolt无线接收器",
          price: 499,
          count: "1万+",
          status: 1,
        },
        {
          id: 8,
          src: require("@/assets/img/goods/8.webp"),
          text: "蒙牛 特仑苏 纯牛奶250ml*16每100ml含3.6g优质蛋白质 礼盒装 品质好礼",
          price: 49,
          count: "900+",
          status: 1,
        },
        {
          id: 9,
          src: require("@/assets/img/goods/9.webp"),
          text: "良品铺子 黑麦全麦面包1000g/箱 早餐粗粮低脂健身代餐全麦面包膳食纤维零蔗糖面包点心吐司零食整箱装",
          price: 39,
          count: "100+",
          status: 1,
        },
        {
          id: 10,
          src: require("@/assets/img/goods/10.webp"),
          text: "闪魔 苹果14钢化膜 iphone14手机膜 22年新款苹果高清抗指纹防刮保护抗蓝光防窥贴膜 【14^加强版】2片+神器 无黑边",
          price: 18,
          count: "300+",
        },
      ],
    };
  },
  methods: {
    showGood(item) {
      this.$router.push({
        name: "goodsdetail",
        query: {
          id: item.id,
          src: item.src,
          price: item.price,
          text: item.text,
        },
      });
    },
  },
};
</script>

<style scoped>
.goods-item {
  width: 369px;
  display: flex;
  align-content: flex-start;
  justify-content: space-around;
  align-items: center;
  flex-wrap: wrap;
}
.goods-item .item {
  width: 170px;
  /* height: 280px; */
  border: 1px solid rgb(218, 218, 218);
  border-radius: 5px;
  margin-bottom: 10px;
}
.goods-item .item .item-detail {
  width: 100%;
}
.goods-item .item .item-detail img {
  width: 170px;
  height: 170px;
}
.desc {
  width: 95%;
  margin: auto;
  /* height: 20px;
  line-height: 20px;
  text-overflow: ellipsis;
  overflow: hidden;
  width: 100px; */
  padding: 3px;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.desc span {
  font-size: 10px;
  padding: 1px 2px 1px 2px;
  background-color: rgb(13, 128, 13);
  color: #ffff;
}
.new-price {
  font-size: 20px;
  color: red;
}
.same {
  display: flex;
  justify-content: space-between;
  padding-right: 5px;
}
.same span:nth-of-type(1) {
  padding: 4px 8px 4px 8px;
  font-size: 10px;
  color: rgb(126, 126, 126);
}
.same span:nth-of-type(2) {
  padding: 4px 8px 4px 8px;
  /* display: inline-block; */
  background-color: rgba(202, 202, 202, 0.295);
  font-size: 12px;
  border-radius: 26px;
}
</style>

⑥、Cates文件夹下index.vue(商品分类页面)

<template>
  <div class="box">
    <div class="head">
      <!-- 搜索框 -->
      <van-search
        v-model="value"
        shape="round"
        background="#fff"
        placeholder="请输入搜索关键词"
      >
        <template #left>
          <van-icon
            name="arrow-left"
            color="#333"
            size="25px"
            style="margin-right: 10px"
          />
        </template>
      </van-search>
    </div>
    <!-- 商品分类 -->
    <div class="cates">
      <van-tree-select
        height="100%"
        :items="items"
        :main-active-index.sync="active"
      >
        <template #content>
          <!-- <van-image
            v-if="active === 0"
            src="https://img01.yzcdn.cn/vant/apple-1.jpg"
          /> -->
          <div class="list-item" v-if="active === 0">
            <p>热门分类</p>
            <van-grid :column-num="3">
              <van-grid-item
                :border="false"
                icon-size="70px"
                v-for="item in hotList"
                :key="item.id"
                :icon="item.src"
                :text="item.name"
              />
            </van-grid>
          </div>
          <div class="list-item" v-if="active === 1">
            <p>热门品牌</p>
            <van-grid :column-num="3">
              <van-grid-item
                :border="false"
                icon-size="70px"
                v-for="item in phoneList"
                :key="item.id"
                :icon="item.src"
                :text="item.name"
              />
            </van-grid>
            <p>手机通讯</p>
            <van-grid :column-num="3">
              <van-grid-item
                :border="false"
                icon-size="70px"
                v-for="item in phoneList"
                :key="item.id"
                :icon="item.src"
                :text="item.name"
              />
            </van-grid>
          </div>
          <!--....... -->
        </template>
      </van-tree-select>
    </div>
  </div>
</template>

<script>
// import { Notify } from "vant";
import listInfo from "./listinfo.js";
export default {
  data() {
    return {
      value: "",
      // 热门导航栏
      hotNav: listInfo.goodsHot,
      // 热门推荐图片
      hotList: listInfo.goodsHotInfo,
      // 手机
      phoneList: listInfo.phoneInfo,

      active: 0,
      items: [
        { text: "热门推荐" },
        { text: "手机数码" },
        { text: "京东超市" },
        { text: "家用电器" },
        { text: "电脑办公" },
        { text: "玩具乐器" },
        { text: "家居厨具" },
        { text: "家具家装" },
        { text: "男装" },
        { text: "男鞋" },
        { text: "女装" },
        { text: "女鞋" },
        { text: "美妆护肤" },
        { text: "医药保健" },
        { text: "酒水饮料" },
        { text: "运动户外" },
      ],
    };
  },
};
</script>

<style scoped>
.van-search {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;
  width: 100%;
}
.box {
  position: relative;
  overflow: hidden;
}
.cates {
  height: 80%;
}
.van-sidebar {
  margin-top: 54px;
}
.van-tree-select__nav {
  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: 100px;
  overflow-y: auto;
  background-color: #f7f8fa;
  -webkit-overflow-scrolling: touch;
}
.van-tree-select__content {
  position: absolute;
  width: 310px;
  height: 100%;
  top: 54px;
  right: 0;
}
.list-item p {
  margin: 10px;
  font-size: 14px;
  color: #333;
  padding-left: 5px;
}
.list-item ::v-deep i.van-icon.van-grid-item__icon {
  font-size: 70px;
}
</style>

⑦、Shopcar文件夹下index.vue(购物车页面)

<template>
  <div class="box">
    <!-- 导航栏 -->
    <van-nav-bar
      title="购物车"
      left-text="返回"
      fixed
      left-arrow
      @click-left="onClickLeft"
    />
    <div class="content">
      <!-- <h2>购物车</h2> -->
      <!-- 购物车 -->
      <van-checkbox-group
        v-model="result"
        style="margin-bottom: 120px; margin-top: 20px"
      >
        <div v-for="(item, index) in goods" :key="item.id">
          <van-checkbox :name="item"></van-checkbox>
          <van-swipe-cell>
            <van-card
              tag="折扣"
              :price="item.price"
              :desc="item.text"
              :title="item.title"
              :thumb="item.src"
              style="margin: 10px 5px"
            >
              <template #tags>
                <van-tag plain type="success" v-if="item.status === 1"
                  >京东超市</van-tag
                >
                <van-tag plain type="danger">双十一促销</van-tag>
              </template>
              <template #num>
                <van-stepper v-model="item.num" />
              </template>
            </van-card>
            <template #right>
              <van-button
                square
                text="删除"
                type="danger"
                class="delete-button"
                @click="del(index)"
              />
            </template>
          </van-swipe-cell>
        </div>
      </van-checkbox-group>

      <!-- <van-card
        num="2"
        price="2.00"
        desc="描述信息"
        title="商品标题"
        thumb="https://img01.yzcdn.cn/vant/ipad.jpeg"
      >
        <template #tags>
          <van-tag plain type="danger">标签</van-tag>
          <van-tag plain type="danger">标签</van-tag>
        </template>
        <template #num>
          <van-stepper v-model="num" />
        </template>
      </van-card> -->

      <!-- 提交订单栏 -->
      <van-submit-bar
        :price="totalPrice"
        button-text="提交订单"
        @submit="onSubmit"
      >
        <van-checkbox v-model="sellAll" @click="handlSellAll"
          >全选</van-checkbox
        >
        <template #tip>
          你的收货地址暂时不支持配送, <span>请修改您的地址</span>
        </template>
      </van-submit-bar>
    </div>
  </div>
</template>

<script>
import { Dialog, Toast } from "vant";
export default {
  data() {
    return {
      sellAll: false,
      cartList: [],
      result: [],
      totalPrice: 0,
      num: 0,
      goods: [
        {
          id: 1,
          src: require("@/assets/img/goods/1.webp"),
          text: "CGVS睡衣女士棉春秋季薄款套头家居服可爱少sadsadas女卡通学生居家长袖套装 YS5251 M(建议身高150-156 体重80-100)",
          price: 98.8,
          count: "17",
          title: "学生居家长袖套装",
          status: 1,
          num: 0,
        },
        {
          id: 2,
          src: require("@/assets/img/goods/2.webp"),
          text: "云米(VIOMI)1.5匹智能家电 变频冷暖Space E AI全域风 新一级以旧换新 壁挂式挂机空调KFRd-35GW/Y2QX2-A1",
          price: 3888.8,
          title: "智能家电",
          count: "18万",
          num: 0,
        },
        {
          id: 3,
          src: require("@/assets/img/goods/3.webp"),
          text: "红毛丹罐头 泰双象 2罐 新鲜毛荔枝双象红毛丹糖水果罐头儿时记忆 红毛丹2罐",
          price: 58.88,
          count: "1万+",
          title: "水果罐头",
          status: 1,
          num: 0,
        },
        {
          id: 4,
          src: require("@/assets/img/goods/7.webp"),
          text: "罗技(Logitech)MX Master 3S 鼠标 无线蓝牙鼠标 办公鼠标 右手鼠标  石墨黑  带Logi Bolt无线接收器",
          price: 499.3,
          count: "1万+",
          title: "罗技(Logitech)MX Master 3S 鼠标",
          status: 1,
          num: 0,
        },
      ],
    };
  },
  watch: {
    result: {
      // 监听商品选择状态
      handler(list) {
        if (list.length == this.goods.length) {
          this.sellAll = true;
        } else {
          this.sellAll = false;
        }
        // 调用价格计算函数
        this.comtalPrice();
      },
      deep: true, //深度监听
    },
  },
  methods: {
    onClickLeft() {
      // this.$router.push({ name: "home" });
      window.history.back();
    },
    // 删除商品
    del(index) {
      Dialog.confirm({
        title: "删除商品",
        message: "确认删除此商品吗",
      })
        .then(() => {
          // on confirm
          console.log(index);
          this.goods.splice(index, 1);
        })
        .catch(() => {
          // on cancel
          return;
        });
    },
    // 全选
    handlSellAll() {
      if (this.sellAll) {
        this.result = this.goods;
      } else {
        this.result = [];
      }
    },
    // 计算总价格
    comtalPrice() {
      let totalPrice = 0;
      this.result.map((item) => {
        totalPrice += item.price * item.num;
      });
      this.totalPrice = parseFloat(totalPrice) * 100;
    },
    // 提交商品订单
    onSubmit() {
      if (this.result.length === 0) {
        Toast.fail("请选择商品再提交");
      } else {
        // Toast.success("成功文案");
        const toast = Toast.loading({
          duration: 0, // 持续展示 toast
          forbidClick: true,
          message: "正在提交 3 秒",
        });

        let second = 3;
        const timer = setInterval(() => {
          second--;
          if (second) {
            toast.message = `正在提交 ${second}`;
          } else {
            clearInterval(timer);
            // // 手动清除 Toast
            Toast.clear();
            Toast.success(`成功!,您花费了${this.totalPrice / 100}`);
            this.result = [];
          }
        }, 1000);
      }
    },
  },
};
</script>

<style scoped>
.box {
  padding-top: 46px;
}
.content {
  /* margin-top: 46px; */
}
.van-submit-bar {
  position: fixed;
  bottom: 50px;
}
.van-checkbox-group .van-button--danger {
  width: 100%;
  height: 100%;
}
</style>

⑧、Mine文件夹下index.vue(用户中心页面)

<template>
  <div class="box">
    <!-- <h2>我的</h2> -->
    <div class="head">
      <van-icon name="user-circle-o" /><a @click="login">京东用户</a>
    </div>
    <div class="user">
      <div class="user-dist">
        <span>商品收藏</span><span>店铺收藏</span><span>我的足迹</span>
      </div>
      <div class="user-dist-icon">
        <van-grid :column-num="4" :border="false">
          <van-grid-item
            v-for="value in icon01"
            :key="value.id"
            :icon="value.icon"
            :text="value.text"
          />
        </van-grid>
      </div>
    </div>
    <div class="user2">
      <div class="user-dist-icon">
        <van-grid :column-num="5" :border="false">
          <van-grid-item
            v-for="value in icon02"
            :key="value.id"
            :icon="value.icon"
            :text="value.text"
          />
        </van-grid>
      </div>
    </div>
    <div class="user3">
      <div class="user-dist-icon">
        <van-grid :column-num="4" :border="false">
          <van-grid-item
            v-for="value in icon03"
            :key="value.id"
            :icon="value.icon"
            :text="value.text"
          />
        </van-grid>
      </div>
    </div>
    <div class="logo"><img src="@/assets/img/mine/logo.png" alt="" /></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      icon01: [
        { id: 1, icon: "credit-pay", text: "待付款" },
        { id: 2, icon: "send-gift-o", text: "待收货" },
        { id: 3, icon: "after-sale", text: "退换/售后" },
        { id: 4, icon: "records", text: "全部订单" },
      ],
      icon02: [
        { id: 1, icon: "discount", text: "优惠券" },
        { id: 2, icon: "balance-list-o", text: "白条额度" },
        { id: 3, icon: "smile-o", text: "京豆" },
        { id: 4, icon: "bill-o", text: "红包" },
        { id: 5, icon: "paid", text: "全部资产" },
      ],
      icon03: [
        { id: 1, icon: "smile-comment-o", text: "客服服务" },
        { id: 2, icon: "todo-list-o", text: "我的预约" },
        { id: 3, icon: "balance-pay", text: "闲置换钱" },
        { id: 4, icon: "replay", text: "高价回收" },
      ],
    };
  },
  methods: {
    login() {
      this.$router.push({ name: "login" });
    },
  },
};
</script>

<style scoped>
.box {
  padding: 46px 30px;
  background-image: linear-gradient(
    60deg,
    rgba(243, 146, 142, 0.151),
    rgba(235, 50, 136, 0.151)
  );
}
.box .head {
  font-size: 23px;
  letter-spacing: 3px;
  color: #333;
}
.box .head .van-icon-user-circle-o {
  font-size: 60px;
  color: red;
  vertical-align: middle;
}
.user,
.user2,
.user3 {
  /* border: 1px solid red; */
  /* padding: 55px; */
  margin-top: 15px;
  border-radius: 8px;
  border: 1px solid rgb(214, 214, 214);
  overflow: hidden;
}
.logo {
  padding: 55px;
  margin-top: 15px;
  border-radius: 8px;
  border: 1px solid rgb(214, 214, 214);
  overflow: hidden;
  background-color: #fff;
  text-align: center;
}
.user .user-dist {
  height: 30px;
  display: flex;
  justify-content: space-around;
  background-color: rgba(236, 236, 236, 0.651);
  align-items: center;
}
.user .user-dist-icon .van-grid-item ::v-deep i.van-icon.van-grid-item__icon,
.user2 .user-dist-icon .van-grid-item ::v-deep i.van-icon.van-grid-item__icon,
.user3 .user-dist-icon .van-grid-item ::v-deep i.van-icon.van-grid-item__icon {
  font-size: 32px;
}
.user
  .user-dist-icon
  .van-grid
  .van-grid-item:nth-of-type(4)
  ::v-deep
  i.van-icon.van-grid-item__icon {
  color: red;
}
.user2
  .user-dist-icon
  .van-grid
  .van-grid-item:nth-of-type(5)
  ::v-deep
  i.van-icon.van-grid-item__icon {
  color: red;
}
</style>

总结

此项目利用vue2+vant,实现京东app商城的首页,商品分类,购物车,用户页面,用户登录,简易商品详情展示,完整代码在此文档中并未展示完全。
项目源码:https://gitee.com/Mr-doudou/simple-imitation-Jingdong-Mall.git

源码说明:克隆到本地电脑之后,进入项目文件,执行npm i 安装相关依赖,npm run serve启动项目。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐