十七、网上商城项目(2)
创始人
2025-05-31 20:22:17
0

本章概要

  • 菜单组件
  • 图书分类组件
  • 广告图片轮播组件
  • 热门推荐组件
  • 新书上市组件
  • 首页组件

17.3.2 菜单组件

菜单是单独定义的一个组件,本项目的菜单只有一级,如果需要定义多级菜单,可参照 《5.3.1》小节的实现。在 components 目录下新建 Menus.vue 。如下:

Menus.vue




这个组件比较简单,都是静态代码。由于本项目只是用于演示基于 Vue 前端开发涉及的各个功能的实现,所以暂时只提供了首页和新书菜单的实现,其它 3 个(特价书、教材、视听教程)功能的实现是类似的,只需要服务端提供相应的接口即可。
首页和新书菜单组件渲染的位置(即 router-view)在 App.vue 中指定。App.vue 的代码如下:

App.vue



本项目没有用到嵌套路由,所有页面级路由组件的渲染都是在这里。换句话说,即所有渲染的页面都有头部和菜单。

17.3.3 图书分类组件

图书分类组件用于显示商品的分类,每个分类都是一个链接,单击链接将跳转到展示该分类下所有商品的页面。
在 components 目录下新建 HomeCategory.vue。如下:

HomeCategory.vue




在 created 生命周期钩子中向服务端请求所有分类数据。服务端提供的该数据的内容如下:
http://111.229.37.167/api/category

[{"id": 1,"name": "Java EE","root": true,"parentId": null,"children": [{"id": 3,"name": "Servlet/JSP","root": false,"parentId": 1,"children": []}, {"id": 4,"name": "应用服务器","root": false,"parentId": 1,"children": []}, {"id": 5,"name": "MVC框架","root": false,"parentId": 1,"children": []}]
}, {"id": 2,"name": "程序设计","root": true,"parentId": null,"children": [{"id": 6,"name": "C/C++","root": false,"parentId": 2,"children": [{"id": 9,"name": "C11","root": false,"parentId": 6,"children": []}]}, {"id": 7,"name": "Java","root": false,"parentId": 2,"children": []}, {"id": 8,"name": "C#","root": false,"parentId": 2,"children": []}]
}]

子分类是放到 children 数组属性中的,本项目中未用到 root 和 parentId 属性,前者可用于列出某个根分类下的所有商品,后者可以用于查找某个分类的父分类,甚至反向查找所有上级分类。
清楚了数据接口返回的数据结构,那么 HomeCategory 组件的代码也就清楚了。

17.3.4 广告图片轮播组件

广告图片轮播功能在电商网站属于标配的功能,其实是通过 JavaScript 代码控制图片的轮播,并处理一些控制图片显示的单击事件。
由于 Vue 3.0 推出的时间还不是特别长,之前 Vue 2.x 下的很多好用的图片轮播插件还没有移植到 Vue 3.0 下,如果自己编写一个成熟的图片轮播组件,又会增加本项目的复杂度,因此这里暂时先用一张静止的图片代替图片轮播。如果对图片轮播功能的实现有兴趣,可以在网上找到很多案例,将其封装为组件使用即可。(不过,此时网上应该已经有支持 Vue 3.0 的图片轮播插件了)。

在 components 目录下新建 HomeScrollPic.vue 。如下:

HomeScrollPic.vue




图片是保存在 public 目录下的,该目录下的资源直接通过根路径“/”引用即可。

17.3.5 热门推荐组件

热门推荐组件用于显示热门商品,用户如果对某一热门商品感兴趣,可以单击该商品链接,进入商品详情页面。
在 components 目录下新建 HomeBooksHot.vue 。如下:

HomeBooksHot.vue




在 created 声明周期钩子中向服务端请求热门商品数据。服务端提供的该数据接口如下:
http://111.229.37.167/api/book/hot
返回的数据结构如下:

[{"id":1,"title":" VC++深入详解(第3版)","author":"孙鑫","price":168,"discount":0.95,"bookConcern":null,"imgUrl":"/api/img/vc++.jpg","bigImgUrl":"/api/img/vc++big.jpg","publishDate":null,"brief":null,"inventory":1000},{"id":2,"title":"Java编程思想","author":"Bruce Eckel","price":108,"discount":0.5,"bookConcern":null,"imgUrl":"/api/img/javathink.jpg","bigImgUrl":"/api/img/javathinkbig.jpg","publishDate":null,"brief":null,"inventory":500},{"id":3,"title":"C Primer Plus 第6版","author":"Stephen Prata","price":89,"discount":0.5,"bookConcern":null,"imgUrl":"/api/img/c++primer.jpg","bigImgUrl":"/api/img/c++primerbig.jpg","publishDate":null,"brief":null,"inventory":400},{"id":4,"title":"Servlet/JSP深入详解","author":"孙鑫","price":139,"discount":0.9,"bookConcern":null,"imgUrl":"/api/img/jsp.jpg","bigImgUrl":"/api/img/jspbig.jpg","publishDate":null,"brief":null,"inventory":1000}
]

实际上,热门推荐组件用不到全部信息,只是服务端的数据接口返回的数据就是如此,那么从这些数据中选择游泳的数据使用即可。

一般电商网站的商品有定价和实际销售价格,在前端展示商品的时候需要同时显示这两种价格。从这里返回的数据来看,服务端只提供了商品的定价和折扣,并没有实际销售价格,那么实际销售价格就需要我们自己来处理。这在实际开发中也很常见,不能期望服务端的开发人员专门为你(当然老板除外)的需求提供一个接口,也许还有其他前端也要用到该接口。

实际价格是定价与折扣相乘得到的,由于实际价格在多处要用到,因此编写一个单独的函数来计算价格。此外,还要考虑价格显示问题,价格只是显示到分就可以了,而在计算过程中,由于是浮点数,可能会出现小数点后两位之后的数据,所以要进行处理。除此之外,价格一般还会加上货币符号,如国内会加上人民币符号¥。为此,再编写一个函数,专门负责价格的格式化问题。

将这两个函数放到单独的 JS 文件中,在 src 目录下新建 utils 文件夹,在该文件夹下新建 util.js。如下:

util.js

const digitsRE = /(\d{3})(?=\d)/gexport function factPrice(value, discount) {value = parseFloat(discount);if (!discount) {return value}return value * discount;
}export function currency(value, currency, decimals) {value = parseFloat(value);if (!isFinite(value) || (!value && value !== 0)) {return ''}currency = currency != null ? currency : '¥';decimals = decimals != null ? decimals : 2;var stringified = Math.abs(value).toFixed(decimals);var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified;var i = _int.length % 3;var head = i > 0 ? (_int.slice(0, i) + (_int.length > 3 ? ',' : '')) : '';var _float = decimals ? stringified.slice(-1 - decimals) : '';var sign = value < 0 ? '-' : '';return sign + currency + head + _int.slice(i).replace(digitsRE, '$1,') + _float
}

为了方便在各个组件内使用这两个函数,在 App 组件内通过 provide 选项向所有后代组件提供这两个函数。编辑 App.vue ,修改后的代码如下:

App.vue



之后记得在组件内使用 inject 选项注入这两个函数,如下:

inject:['factPrice','currency']

17.3.6 新书上市组件

新书上市组件用于显示刚上市的商品,用户如果对某一商品感兴趣,可以单击该商品链接,进入商品详情页面。
在 components 目录下新建 BooksNew.vue,由于该组件会被复用,所以这里没有使用主页的前缀 Home。

BooksNew.vue



在 created 生命周期钩子中向服务端请求新书的数据。服务端提供的该数据接口如下:
http://111.229.37.167/api/book/new
返回的数据形式同 /book/hot。

17.3.7 首页组件

首页的各个组成部分编写完成后,就可以开始集成这几个部分了。首页作为页面级组件,放到 views 目录下。在 views 目录下新建 Home.vue 。如下:

src/views/Home.vue


Home 组件比较简单,只是用于拼接各个子组件

其它,后面启动的时候可能会出现以下命名规则错误

在这里插入图片描述

修改 .eslintrc.js,如下:

//在rules中添加自定义规则
//关闭组件命名规则
"vue/multi-word-component-names": "off",

在这里插入图片描述

相关内容

热门资讯

高达1340亿美元!美媒:马斯... 来源:环球网【环球网报道】据美国彭博社、路透社当地时间17日报道,美国亿万富翁埃隆·马斯克要求美国开...
605028,突然终止“易主”... 下周合计解禁市值464.99亿元。世茂能源(605028)1月16日晚间公告表示,停牌期间,公司控股...
江波龙股东拟减持3%  市值约... 中经记者 陈佳岚 广州报道2026年1月16日晚间,存储模组龙头江波龙(301308.SZ)发布股东...
被质疑的梦想,才值得追觅 我们都经历过这样一种时刻:你做了一个决定,没人理解;你选择一条路,所有人都说你「太狂」、「不可能实现...
2月1日起,提供“静音车厢”的... 今天(17日),记者从国铁集团获悉, 自2月1日起,“静音车厢”服务将拓展至除动卧列车之外的“D”字...
云南知名国企换帅,人均薪酬超3... 【高管动态】担任贵研铂业董事长不到两年时间,王建强辞去董事长职务,继任者为80后。1月17日,云南省...
4900万投资变“烂账” 主业... 2026年1月12日,一场始于约八年前的股权投资交易纠纷正式进入司法程序。安正时尚最新披露的公告显示...
2025商业店装与展陈行业技术... 中国商报(记者 彭婷婷)场景,一头连着产业、技术,一头连着消费市场,具有整体性、协同性等特点。如何进...
追觅科技CEO俞浩发声:怼人的... 红星资本局1月17日消息,1月17日上午,追觅科技创始人兼CEO俞浩发微博回应近期争议。他称,打造人...
查办重大案件表现突出,证监会表... “证监会发布”消息,1月16日,中国证监会第十四届稽查办案表彰奖励会在京召开。会议深入贯彻落实党的二...