使用vant4+vue3制作电商购物网站

一、前言

1.本项目基于vant4+vue3构建,默认友友们已具备相关知识,如不具备,请友友们先去了解相关该概念

2.项目数据来源于开源框架 新峰商城 在此指出

3.此项目目的在于帮助友友们了解基本的用法,没有涉及太多的逻辑操作。

二、项目介绍

首页

分类

我的

三、项目搭建

大家可以看看项目所需的依赖,具体的安装命令如下

axios

npm install axios --save

less(为了书写样式方便,不需要强制安装)

npm install less --save

mockjs(使用mockjs制造假数据)

npm install mockjs --save

vant(可以去官网看看组件的使用用法)

npm i vant

vue-router(必须要的哈,进行页面切换的)

npm install vue-router

安装为项目所需的依赖,我们需要将需要的依赖引入我们的项目中

在main.js中引入并使用安装好的vant

创建路由并加载到main.js

路由的配置

注意:路由文件所需要的home、user、cag组件自己先定义好,然后引入到路由文件中,大家也可以使用懒加载的方式,具体组件的创建就不演示了。

四、页面制作

在配置完路由之后,思考我们的配置的路由是做什么的。通常为了页面的切换,我们会需要一个固定在顶部的导航条,我们称之为tabbar,且所有的页面都能看到这个导航条

首页显示

路由配置结束,需要将其显示出来,路由出口配置在app.html页面

在本项目中,我将首页重定向到home页面,所有接下来的所有操作,我们去到home页面

这是home页面的结构,包括搜索框、轮播图、商品分类、商品显示,顶部导航,有经验的小伙伴可以看看view文件夹和components文件夹,这里我将具体的页面放在view下,其余组件拆分放到components

具体显示效果如下

现在我们拆分这个页面

搜索框

代码

<template>
    <van-sticky>
        <van-search
          shape="round"
          background="#1baeae"
          placeholder="请输入搜索关键词"
        >
 
        </van-search>
    </van-sticky>

</template>

van-sticky为黏性布局,也就是鼠标向下滑动,搜索框会固定在顶部

轮播图(swiper)

代码

<template>
    <van-swipe :autoplay="3000" lazy-render>
      <van-swipe-item v-for="(item,index) in newGoods.carousels" :key="index">
        <img :src="item.carouselUrl" />
  </van-swipe-item>
</van-swipe>
</template>
<script setup>
    import {onMounted,reactive} from "vue"
    import request from "../mock/request.js"
    const newGoods = reactive(
        {
            carousels:[]
        }
    )
    onMounted(async() =>{
        let result = await request({
          url:'/mock/getGoods',
          method:'get'
      })
      if(result.data.code === 200){
          newGoods.carousels = result.data.data.carousels
      }
     
    })
</script>
<style type="text/css" media="all" scoped>
    img{
        width: 100%;
        height: 200px;
    }
</style>

这里大家看看mock中我们写的假的json数据

{
     "carousels": [
      {
        "carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/2024-05/6580fa613c574939a84e0a04e288292b.jpg",
        "redirectUrl": "https://juejin.im/book/6844733826191589390"
      },
      {
        "carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/202405/240051cba47c47d384142a253d50cb6d.png",
        "redirectUrl": "https://juejin.im/book/6844733826191589390"
      },
      {
        "carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/202406/c16311df062d43c49f9e692728b5efd4.jpg",
        "redirectUrl": "https://juejin.im/book/6844733826191589390"
      },
      {
        "carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/2024-05/1e56a1ce74b8447baaf08b87eaf007ec.jpg",
        "redirectUrl": "https://juejin.im/book/6844733826191589390"
      }
      
    ]
}

看看mockserver.js文件,如果小伙伴写过node的话,这里应该很好理解

这里写了三个接口,对于的三个页面数据,轮播图中用的数据都在goods中,在request文件中,只是简单的对超时做了限制

此项目不需要我们我们二次封装axios

了解完这些前置知识和后,我们在认真关注下我们的swiper组件中的内容

认真看完上面教程,给位友友们应该可以将轮播图正确显示出来了

商品分类

代码

<template>
    <van-grid clickable   :column-num="5">
      <van-grid-item to="/cag" v-for="(value,index) in categoryList.list" :key="index"  :text="value.name">
          <van-image :src="value.imgUrl"></van-image>
          <span>{{value.name}}</span>
      </van-grid-item>
    </van-grid>

</template>
<script setup>
    import {onMounted,reactive} from "vue"
    import request from "../mock/request.js"
    const categoryList = reactive(
        {
            list:[]
        }
    )
    onMounted(async() =>{
        let result = await request({
          url:'/mock/getCategoryList',
          method:'get'
      })
      if(result.data.code === 200){
          categoryList.list = result.data.data
      }
      
    })
</script>
<style type="text/css" media="all" >
    .van-image__img{
        width: 50px !important;
        height: 50px !important;
    }
    span{
        font-size: 20px !important;
    }
</style>

我们看看这个页面的结构

mock中的数据

商品页面

代码

<template>
    <header class="good-header">新品上线</header>
    <div class="good-box" >
          <div class="good-item" v-for="item in newGoods.newGoods" :key="item.goodsId" @click="goToDetail(item)">
            <img :src="item.goodsCoverImg" alt="">
            <div class="good-desc">
              <div class="title">{{ item.goodsName }}</div>
              <div class="price">¥ {{ item.sellingPrice }}</div>
            </div>
          </div>
    </div>
   
      
</template>
<script setup>
    import { useRouter } from 'vue-router'
    import {onMounted,reactive} from "vue"
    import request from "../mock/request.js"
    const router = useRouter();
    const newGoods = reactive(
        {
            newGoods:[],
            hots: [],
            recommends: [],
        }
    )
    onMounted(async() =>{
        let result = await request({
          url:'/mock/getGoods',
          method:'get'
      })
      if(result.data.code === 200){
          newGoods.newGoods = result.data.data.newGoodses
          newGoods.hots = result.data.data.hotGoodses
          newGoods.recommends = result.data.data.recommendGoodses
      }
     
    })
    const goToDetail = (item) => {
      router.push({ path: `/product/${item.goodsId}` })
    }
</script>
<style  scoped>

    .good-header {
      background: #f9f9f9;
      height: 50px;
      line-height: 50px;
      text-align: center;
      color: #1baeae;
      font-size: 25px;
      font-weight: 500;
    }
   .good-box {
      display: flex;
      justify-content: flex-start;
      flex-wrap: wrap;
      
    }
   .good-item {
        box-sizing: border-box;
        width: 50%;
        border-bottom: 1PX solid #e9e9e9;
        padding: 10px 10px;
        
    }
    .good-item:nth-child(2n + 1) {
          border-right: 1PX solid #e9e9e9;
    }
    img {
      display: block;
      width: 120px;
      margin: 0 auto;
    }
    .good-desc {
      text-align: center;
      font-size: 20px;
      padding: 10px 0;
     
    }
      .title {
        color: #222333;
      }
      .price {
        color:#1baeae;
      } 
      
</style>

代码解释

点击挑转到商品详情

详情页面也是一致的,大家看情况编写。由于涉及到后续的购物车,所有我没有继续往下写了

底部导航

代码

<template>
    <van-tabbar v-model="active" class="bar"> 
      <van-tabbar-item icon="home-o" to="/home">首页</van-tabbar-item>
      <van-tabbar-item icon="search" to="/cag">分类</van-tabbar-item>
      <van-tabbar-item icon="friends-o" to="/user">个人</van-tabbar-item>
    </van-tabbar>
</template>

<script setup>
import { ref} from "vue"
    const active = ref('home');
</script>
<style type="text/css" >
    .bar{
        margin-top: 40px !important;
        
    }
    .van-tabbar-item{
        font-size: 16px !important;
    }
</style>

这里的代码就不做解释了,相信大家都能看懂

将所需要要的组件引入即可

分类页面

分类页面比较简单,经过首页一节的铺垫,现在我们将节奏快点

页面分为上中下三层。上层为搜索框;中间左侧为侧边栏,右边为商品;下层为导航条

代码

<template>
    <TabNav></TabNav>
    <div class="container">
        <SliderNav></SliderNav>
        <CagGoods></CagGoods>
    </div>
    <div style="width:100%;height:40px"></div>
    <Tabbar></Tabbar>
</template>
<script setup>
    import Tabbar from "../components/Tabbar.vue"
    import TabNav from "../components/TabNav.vue"
    import SliderNav from "../components/SliderNav.vue"
    import CagGoods from "../components/CagGoods.vue"
    
</script>
<style scoped>
    .container{
        display: flex;
        flex-direction: row;
    }
    .container .van-sidebar  {
        flex: 2;
    }
    .container .van-grid{
        flex: 10;
    }
</style>

这里贴出的代码是为了方便大家布局使用的

顶部导航

侧边栏

右侧goods

我的

<template>
    <div class="user">
        <Card></Card>
        <div class="box">
            <van-icon name="setting-o" class="setting"/>
            <span>设置</span>
        </div>
        <div class="box1">
           <van-icon name="service-o" class="service" ></van-icon>
            <span>联系客服</span>
        </div>
       
        <MyOrder></MyOrder>
        <MySerive></MySerive>
    </div>
    <Tabbar></Tabbar>
</template>
<script setup>
    import Tabbar from "../components/Tabbar.vue"
    import Card from "../components/Card.vue"
    import MyOrder from "../components/MyOrder.vue"
    import MySerive from "../components/MySerive.vue"
    
</script>
<style >
    .user{
        position: relative;
    }
    .van-card__title {
        font-size: 20px !important;
        margin-top: 10px;
        height: 30px !important;
        line-height: 30px;
    }
   
   
    .box{
        display: flex;
        position: absolute;
        top: 10px;
        right: 20px;
        font-size: 25px;
        flex-direction: column;
    }
     .box1{
        display: flex;
        position: absolute;
        justify-content:center;
        align-content: center;
        top: 10px;
        right: 80px;
        font-size: 25px;
        flex-direction: column;
    }
    .service{
        text-align: center;
    }
    span{
        font-size: 12px;
    }
   
</style>

MyOrder

<template>
    <div class="temp">
        <div class="top">
            <span class="order">我的订单</span>
            <span class="all">全部></span>
        </div>
        <div class="content">
            <div>
                 <van-icon name="shop-o" />
                <span>待付款</span>
            </div>
             <div>
                <van-icon name="gift-card-o" />
                <span>待发货</span>
            </div>
             <div>
                <van-icon name="setting-o" class="setting"/>
                <span>待收货</span>
            </div>
             <div>
                <van-icon name="chat-o" />
                <span>待评价</span>
            </div>
             <div>
                 <van-icon name="balance-o" />
                <span>退款/售后</span>
            </div>
        </div>
    </div>
</template>
<script>
    
</script>
<style scoped>
    *{
        margin: 0;
        padding: 0;
     
    }
    .temp{
        display: flex;
        flex-direction: column;
        margin-top: 5px;
        transition: 0.3s;
        margin: 10px;
        padding: 10px;
        border-radius: 5px;
        background: #1baeae;
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
        overflow: hidden;
    }
     .temp:hover{
         box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
     }
    .top{
        display: flex;
        justify-content: space-between;
        align-content: center;
    }
    .order{
        font-size: 20px;
    }
    .all{
        margin-right: 20px;
    }
    .content{
        display: flex;
        flex-direction: row;
        justify-content: center;
    }
    .content div{
        margin-top: 10px;
        margin-left: 20px;
        display: flex;
        flex-direction: column;
        flex: 1;
        text-align: center;
    }
    .content div span{
        margin-top: 5px;
    }
</style>

这里大家掌握flex布局即可写出

MySerive

这个页面其实也是一样的,只是一个横向,一个纵向

写在最后

到这里就算写完了,希望各位友友们可以自己多加思考,清楚掌握。

同时也请大家多多点赞支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/739761.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

宝塔面板一键迁移项目站点教程

此插件仅用于将当前机器数据迁移出去&#xff0c;数据接收机器无需安装此插件。 注意事项&#xff1a; 当前教程仅适用《宝塔一键迁移API版本》插件&#xff0c;版本号 >3.0。 推荐迁移面板版本 > 6.9.5&#xff0c;低版本迁移可能存在部分数据无法迁移成功。 面板版…

Future You:对话未来的自己

是由麻省理工开发的 AI 聊天机器人&#xff0c;通过填写一系列表单和上传自己的照片&#xff0c;即可看到老年后的自己并与之对话。

怎么将图片压缩调小?在线压缩图片的4种快捷方法

压缩图片是日常很常用的一个图片处理功能&#xff0c;现在拍摄和制作的图片都比较大&#xff0c;在使用时经常会受到影响。在遇到无法上传、传输过慢的问题时会降低工作效率&#xff0c;所以掌握一招快速压缩图片是非常重要的。通过下面这篇文章来给大家介绍一下在线图片压缩的…

193.回溯算法:组合总和(力扣)

代码解决 class Solution { public:vector<int> res; // 当前组合的临时存储vector<vector<int>> result; // 存储所有符合条件的组合// 回溯函数void backtrcing(vector<int>& nums, int target, int flag, int index) {// 如果当前组合的和超过了…

预备役二招算法测试题解

这次题目出的都是一些偏向于基础的题目&#xff0c;就是一些简单的模拟&#xff0c;思维&#xff0c;以及基础算法&#xff08;二分&#xff0c;前缀和&#xff09; &#xff08;点击题目标题&#xff0c;进入原题&#xff09; 我是签到题 题解&#xff1a;就是说给你 t 组数据…

【MDK5问题】:MDK中的jlink正常下载,但是板子却没有任何反应

1、问题现象&#xff1a; 1、在MDK5中&#xff0c;jlink配置项如下图&#xff0c;没有看到异常情况和配置&#xff1a; 2、点击load下载到板子上&#xff0c;出现的现象是&#xff0c;下载提示下载完成&#xff0c;但是&#xff0c;板子却没有任何反应&#xff08;程序实现应该…

音频傅里叶变换(基于开源kissffs)

主要参考资料&#xff1a; 深入浅出的讲解傅里叶变换&#xff08;真正的通俗易懂&#xff09;: https://zhuanlan.zhihu.com/p/19763358 推荐开源项目&#xff1a;KISS FFT&#xff1a; https://blog.csdn.net/gitblog_00031/article/details/138840117 数字硅麦数据的处理&…

【Linux】基础IO_1

文章目录 六、基础IO1. C语言的文件接口2. 系统文件I/O 未完待续 六、基础IO 1. C语言的文件接口 我们知道 文件 文件内容 文件属性 。即使是一个空文件&#xff0c;仍然会在磁盘中占据空间。那打开文件是什么意思呢&#xff1f;其实文件打开的意思就是&#xff1a;将文件从…

上海舆情分析软件的功能和对企业的意义

随着互联网的飞速发展&#xff0c;人们参与讨论、发声的途径与评率也越来越多&#xff0c;在为自己发声的同时&#xff0c;公众舆论也成为企业获取民意&#xff0c;改进发展的重要参考。 上海 舆情分析软件的开发&#xff0c;为企业获取舆论&#xff0c;调查研究提供了便捷化的…

探寻Scala的魅力:大数据开发语言的入门指南

大数据开发语言Scala入门 一、引言1.1 概念介绍1.2 Scala作为大数据开发语言的优势和应用场景1.2.1 强大的函数式编程支持1.2.2 可与Java无缝集成1.2.3 高性能和可扩展性1.2.4 大数据生态系统的支持 二、Scala基础知识2.1. Scala简介&#xff1a;2.1.1 Scala的起源和背景2.1.2 …

【Win】USB设备连接与移除的实时追踪

在这个信息爆炸的时代&#xff0c;USB设备成了我们不可或缺的数据伴侣。但你有没有想过&#xff0c;当你的USB突然消失&#xff0c;或者你不确定它何时被拔出&#xff0c;这可能会让你陷入困境。别担心&#xff0c;即使Windows系统没有默认提供监控功能&#xff0c;我们也可以轻…

fairseq (Facebook AI Research) 包

0. Abstract 最近在看一个用 RNNs 网络做 Translation 任务的程序, 关于数据处理部分, 主要用到工具包 sentencepiece 和 fairseq, 前者主要是对文本进行分词处理, 后者则是对已分词的文本进行二进制化和快速加载. 包越方便使用, 就说明包装得越狠, 也就越令人一头雾水, 本文简…

巧用newSingleThreadExecutor让异步任务顺序跑

背景 Flume 是 Cloudera 提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统 。一个用来控制 Flume 采集任务的 Web 应用&#xff0c;需要对任务进行管理&#xff0c;主要操作「启动、停止、新建、编辑、删除」&#xff0c;本质就是对…

神经网络实战2-损失函数和反向传播

其实就是通过求偏导的方式&#xff0c;求出各个权重大小 loss函数是找最小值的&#xff0c;要求导&#xff0c;在计算机里面计算导数是倒着来的&#xff0c;所以叫反向传播。 import torch from torch.nn import L1Lossinputstorch.tensor([1,2,3],dtypetorch.float32) targe…

品牌策划背后的秘密:我为何对此工作情有独钟?

你是否曾有过一个梦想&#xff0c;一份热爱&#xff0c;让你毫不犹豫地投身于一个行业&#xff1f; 我就是这样一个对品牌策划充满热情的人。 从选择职业到现在&#xff0c;我一直在广告行业里“混迹”&#xff0c;一路走来&#xff0c;也见证了许多对品牌策划一知半解的求职…

RubyMine 2024 mac/win版:智慧编程,从心出发

JetBrains RubyMine 2024 是一款专为Ruby和Rails开发者打造的高效集成开发环境(IDE)。它凭借其卓越的性能和丰富的功能&#xff0c;帮助开发者在Ruby和Rails的开发过程中提升效率&#xff0c;减少错误。 RubyMine 2024 mac/win版获取 RubyMine 2024 提供了强大的代码编辑功能&…

mp4转换成mp3怎么转?教你几种值得收藏的转换方法!

mp4转换成mp3怎么转&#xff1f;MP4&#xff0c;这一深入人心的数字多媒体容器格式&#xff0c;无疑在当今数字世界中占据了一席之地&#xff0c;那么&#xff0c;它究竟有何过人之处呢&#xff1f;首先&#xff0c;MP4的跨平台兼容性是其一大亮点&#xff0c;不论是在Windows的…

免费的AI在线写作工具,让写作变的更简单

在如今的时代&#xff0c;写作已经成为了我们日常生活中不可或缺的一部分。无论是自媒体创作者、学生还是办公职场人员&#xff0c;都有内容创作的需求。然而&#xff0c;写作过程往往伴随着灵感枯竭、查找资料费时等问题。下面小编就来和大家分享几款免费的AI在线写作工具&…

cube studio开源一站式机器学习平台:k3s部署cube-studio

全栈工程师开发手册 &#xff08;作者&#xff1a;栾鹏&#xff09; 一站式云原生机器学习平台 前言 开源地址&#xff1a;https://github.com/tencentmusic/cube-studio cube studio 腾讯开源的国内最热门的一站式机器学习mlops/大模型训练平台&#xff0c;支持多租户&…

超级缓存神器:Memcached解密 - 加速你的网站速度

Memcached介绍和详解 1. 简介1.1 什么是Memcached1.2 Memcached的目标和特点1.3 Memcached的优势和适用场景 2. 架构和原理2.1 Memcached的客户端-服务器模型2.2 Memcached的内存存储结构2.3 Memcached的数据访问和数据存储流程2.3.1 数据访问流程2.3.2 数据存储流程 3. 安装和…