[TOC]
## 步骤 1 : homePage.jsp 的复杂性
在homePage中要显示如下内容
1 天猫超市连接右侧有4个分类数据
2 竖状导航栏显示17个分类数据
3 每个分类又再对应不同的推荐产品集合
4 中部会显示17个分类
5 每个分类又显示前5款产品
6 每款产品又会显示第一张图片,标题,价格等信息
倘若把这些功能都在一个jsp中开发出来看,那么这个jsp就会变得非常的长,并且难以维护和扩展。在这里,就可以借鉴home.jsp的思路,把一个大的页面,拆成各个小的jsp,这样维护起来就相对容易了
项目页面结构图:
![](https://box.kancloud.cn/886f4321e9dda10b78d21d60a1f72ec0_393x506.png)
## 步骤 2 : homePage.jsp 所包含页面关系
1. categoryAndcarousel.jsp
分类和轮播
1.1 categoryMenu.jsp
竖状分类菜单
1.2 productsAsideCategorys.jsp
竖状分类菜单右侧的推荐产品列表
1.3 carousel.jsp
轮播
2. homepageCategoryProducts.jsp
总体17种分类以及每种分类对应的5个产品
![](https://box.kancloud.cn/7789c78f6e0bb9f31beec5f03b28a918_674x498.png)
## 步骤 3 : categoryAndcarousel.jsp
categoryAndcarousel.jsp 页面利用ForeController传递过来的数据,天猫国际几个字旁边显示4个分类超链
另外包含了其他3个页面:
categoryMenu.jsp
productsAsideCategorys.jsp
carousel.jsp
这3个页面在接下来的步骤就会讲到
### 猫耳朵效果讲解
首先看下面的css, 这是用来使得猫耳朵图片隐藏并且是绝对定位状态
~~~
img.catear {
position: absolute;
height: 15px;
display: none;
}
~~~
监听菜单鼠标移入事件mouseenter,当鼠标移入的时候,获取当前span的左,上和宽度信息,根据这些信息,计算出猫耳朵应该出现的位置,然后通过css设置猫耳朵的left和top数据, 最后使用fadeIn(500),在半秒内淡入猫耳朵图片。
~~~
$("div.rightMenu span").mouseenter(function(){
var left = $(this).position().left;
var top = $(this).position().top;
var width = $(this).css("width");
var destLeft = parseInt(left) + parseInt(width)/2;
$("img#catear").css("left",destLeft);
$("img#catear").css("top",top-20);
$("img#catear").fadeIn(500);
});
~~~
当鼠标移出的时候,隐藏猫耳朵
~~~
$("div.rightMenu span").mouseleave(function(){
$("img#catear").hide();
});
~~~
### 显示和隐藏效果讲解
左侧的菜单项div的class是eachCategory
`<div class="eachCategory" cid="83">`
右侧的产品列表div的class是productsAsideCategorys
`<div class="productsAsideCategorys" cid="83" style="display: none;">`
首先每个菜单项eachCategory都有一个cid属性,取的是该分类的id值
然后这个菜单项对应的产品列表,也有一个一样的cid属性。
整体思路是:
1. 把所有的产品列表都隐藏
2. 当鼠标移动到菜单项上的时候,取出对应的cid
3. 根据cid,找到对应的产品列表
4. 显示该产品列表
5. 当鼠标移开的时候,隐藏对应的产品列表
显示产品列表函数
~~~
function showProductsAsideCategorys(cid){
$("div.eachCategory[cid="+cid+"]").css("background-color","white");
$("div.eachCategory[cid="+cid+"] a").css("color","#87CEFA");
$("div.productsAsideCategorys[cid="+cid+"]").show();
}
~~~
隐藏产品列表函数
~~~
function hideProductsAsideCategorys(cid){
$("div.eachCategory[cid="+cid+"]").css("background-color","#e2e2e3");
$("div.eachCategory[cid="+cid+"] a").css("color","#000");
$("div.productsAsideCategorys[cid="+cid+"]").hide();
}
~~~
当鼠标移入菜单项的时候,显示对应的产品列表
~~~
$("div.eachCategory").mouseenter(function(){
var cid = $(this).attr("cid");
showProductsAsideCategorys(cid);
});
~~~
当鼠标移出菜单项的时候,隐藏对应的产品列表
~~~
$("div.eachCategory").mouseleave(function(){
var cid = $(this).attr("cid");
hideProductsAsideCategorys(cid);
});
~~~
当鼠标移入产品列表的时候,显示对应的产品列表
~~~
$("div.productsAsideCategorys").mouseenter(function(){
var cid = $(this).attr("cid");
showProductsAsideCategorys(cid);
});
~~~
当鼠标移出产品列表的时候,隐藏对应的产品列表
~~~
$("div.productsAsideCategorys").mouseleave(function(){
var cid = $(this).attr("cid");
hideProductsAsideCategorys(cid);
});
~~~
homePage.jsp:
```
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<script>
/* 显示产品列表函数 */
function showProductsAsideCategorys(cid) {
/* 选择class是eachCategory,属性cid值的某个cid具体值的div, 把背景色修改成白色 */
$("div.eachCategory[cid=" + cid + "]").css("background-color", "white");
/* 选择class是eachCategory,属性cid值的某个cid具体值的div 下面的超链, 把颜色修改成#87CEFA */
$("div.eachCategory[cid=" + cid + "] a").css("color", "#87CEFA");
/* 选择class是productsAsideCategorys,属性cid值的某个cid具体值的div ,显示出来 */
$("div.productsAsideCategorys[cid=" + cid + "]").show();
}
/* 隐藏产品列表函数 */
function hideProductsAsideCategorys(cid) {
$("div.eachCategory[cid=" + cid + "]").css("background-color",
"#e2e2e3");
$("div.eachCategory[cid=" + cid + "] a").css("color", "#000");
$("div.productsAsideCategorys[cid=" + cid + "]").hide();
}
$(function() {
/* 当鼠标移入菜单项的时候,显示对应的产品列表 */
$("div.eachCategory").mouseenter(function() {
var cid = $(this).attr("cid");
showProductsAsideCategorys(cid);
});
/* 当鼠标移出菜单项的时候,隐藏对应的产品列表 */
$("div.eachCategory").mouseleave(function() {
var cid = $(this).attr("cid");
hideProductsAsideCategorys(cid);
});
/* 当鼠标移入产品列表的时候,显示对应的产品列表 */
$("div.productsAsideCategorys").mouseenter(function() {
var cid = $(this).attr("cid");
showProductsAsideCategorys(cid);
});
/* 当鼠标移出产品列表的时候,隐藏对应的产品列表 */
$("div.productsAsideCategorys").mouseleave(function() {
var cid = $(this).attr("cid");
hideProductsAsideCategorys(cid);
});
/* 监听菜单鼠标移入事件,计算猫耳朵显示位置 */
$("div.rightMenu span").mouseenter(function() {
var left = $(this).position().left;
var top = $(this).position().top;
var width = $(this).css("width");
var destLeft = parseInt(left) + parseInt(width) / 2;
$("img#catear").css("left", destLeft);
$("img#catear").css("top", top - 20);
$("img#catear").fadeIn(500);
});
/* 鼠标移出的时候,隐藏猫耳朵 */
$("div.rightMenu span").mouseleave(function() {
$("img#catear").hide();
});
/* 根据轮播图的位置,设定分类菜单,产品列表等的距离 */
var left = $("div#carousel-of-product").offset().left;
$("div.categoryMenu").css("left", left - 20);
$("div.categoryWithCarousel div.head").css("margin-left", left);
$("div.productsAsideCategorys").css("left", left - 20);
});
</script>
<img src="img/site/catear.png" id="catear" class="catear" />
<div class="categoryWithCarousel">
<div class="headbar">
<div class="head ">
<span style="margin-left: 10px" class="glyphicon glyphicon-th-list"></span> <span style="margin-left: 10px">商品分类</span>
</div>
<div class="rightMenu">
<span><a href=""><img src="img/site/chaoshi.png" /></a></span> <span><a href=""><img src="img/site/guoji.png" /></a></span>
<c:forEach items="${cs}" var="c" varStatus="st">
<c:if test="${st.count<=4}">
<span> <a href="forecategory?cid=${c.id}"> ${c.name} </a></span>
</c:if>
</c:forEach>
</div>
</div>
<div style="position: relative">
<!-- 分类列表 -->
<%@include file="categoryMenu.jsp"%>
</div>
<div style="position: relative; left: 0; top: 0;">
<!-- 分类列表左侧产品列表 -->
<%@include file="productsAsideCategorys.jsp"%>
</div>
<!-- 轮播图 -->
<%@include file="carousel.jsp"%>
<div class="carouselBackgroundDiv"></div>
</div>
```
## 步骤 4 : categoryMenu.jsp
categoryMenu.jsp 显示左侧的竖状分类导航
![](https://box.kancloud.cn/97a7ee8e29a4ab087e47339cd1de6468_223x541.png)
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<div class="categoryMenu">
<c:forEach items="${cs}" var="c">
<div cid="${c.id}" class="eachCategory">
<span class="glyphicon glyphicon-link"></span>
<a href="forecategory?cid=${c.id}">
${c.name}
</a>
</div>
</c:forEach>
</div>
~~~
## 步骤 5 : productsAsideCategorys.jsp
productsAsideCategorys.jsp 进行了三层遍历
1. 先取出每个分类
2. 然后取出每个分类的productsByRow集合
3. 根据productsByRow集合,取出每个产品,把产品的subTitle信息里的第一个单词取出来显示。
JQuery代码解释:
> 这个是用于随机挑选一个产品作为推荐产品,来进行高亮显示。 严格的说,应该是后台设置那个产品是推荐产品,这里不做那么复杂,直接在前端按照20%的概率,随机挑选了一个产品。
~~~
$("div.productsAsideCategorys div.row a").each(function(){
var v = Math.round(Math.random() *4);
if(v == 1)
$(this).css("color","#87CEFA");
});
~~~
![](https://box.kancloud.cn/eb2415ce2d7ec1ace1062c6b2a0ee3fb_433x72.png)
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<script>
$(function(){
$("div.productsAsideCategorys div.row a").each(function() {
var v = Math.round(Math.random() *4);
if(v == 1) {
$(this).css("color","#87CEFA");
}
});
});
</script>
<c:forEach items="${cs}" var="c">
<div cid="${c.id}" class="productsAsideCategorys">
<c:forEach items="${c.productsByRow}" var="ps">
<div class="row">
<c:forEach items="${ps}" var="p">
<c:if test="${!empty p.subTitle}">
<a href="foreproduct?pid=${p.id}">
<c:forEach items="${fn:split(p.subTitle, ' ')}" var="title" varStatus="st">
<c:if test="${st.index==0}">
${title}
</c:if>
</c:forEach>
</a>
</c:if>
</c:forEach>
<div class="seperator"></div>
</div>
</c:forEach>
</div>
</c:forEach>
~~~
> 拓展资料
> fn标签提供各种实用功能,首先使用之前使用加入如下指令
> `<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> `
>
> fn:split(string, separator)
> 返回一个数组,以参数separator 为分割符分割参数string,分割后的每一部分就是数组的一个元素
> 当然也可在后台Java代码,即service中实现。
## 步骤 6 : carousel.jsp
轮播部分,都是静态的页面,没有用到服务端数据
![](https://box.kancloud.cn/33b2bad44ee704cb7bb024953b0f1ed2_683x508.png)
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<div id="carousel-of-product" class="carousel-of-product carousel slide1" data-ride="carousel">
<!-- 指示符 -->
<ol class="carousel-indicators">
<li data-target="#carousel-of-product" data-slide-to="0" class="active"></li>
<li data-target="#carousel-of-product" data-slide-to="1"></li>
<li data-target="#carousel-of-product" data-slide-to="2"></li>
<li data-target="#carousel-of-product" data-slide-to="3"></li>
</ol>
<!-- 轮播图片 -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img class="carousel carouselImage" src="img/lunbo/1.jpg">
</div>
<div class="item">
<img class="carouselImage" src="img/lunbo/2.jpg">
</div>
<div class="item">
<img class="carouselImage" src="img/lunbo/3.jpg">
</div>
<div class="item">
<img class="carouselImage" src="img/lunbo/4.jpg">
</div>
</div>
<!-- 左右切换按钮 -->
<!-- <a class="left carousel-control" href="#carousel-of-product" role="button" data-slide="prev"> -->
<!-- <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span> -->
<!-- </a> -->
<!-- <a class="right carousel-control" href="#carousel-of-product" role="button" data-slide="next"> -->
<!-- <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> -->
<!-- </a> -->
</div>
~~~
## 步骤 7 : homepageCategoryProducts.jsp
homepageCategoryProducts.jsp 进行了2次遍历
1. 遍历所有的分类,取出每个分类对象
2. 遍历分类对象的products集合,取出每个产品,然后显示该产品的标题,图片,价格等信息
![](https://box.kancloud.cn/ae55abc547a2c71b05648b70489d536a_999x697.png)
~~~
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix='fmt' uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<div class="homepageCategoryProducts">
<c:forEach items="${cs}" var="c" varStatus="stc">
<div class="eachHomepageCategoryProducts">
<div class="left-mark"></div>
<span class="categoryTitle">${c.name}</span>
<br>
<c:forEach items="${c.products}" var="p" varStatus="st">
<c:if test="${st.count<=5}">
<div class="productItem" >
<a href="foreproduct?pid=${p.id}"><img width="100px" src="img/productSingle_middle/${p.firstProductImage.id}.jpg"></a>
<a class="productItemDescLink" href="foreproduct?pid=${p.id}">
<span class="productItemDesc">[热销]
${fn:substring(p.name, 0, 20)}
</span>
</a>
<span class="productPrice">
<fmt:formatNumber type="number" value="${p.promotePrice}" minFractionDigits="2"/>
</span>
</div>
</c:if>
</c:forEach>
<div style="clear:both"></div>
</div>
</c:forEach>
<img id="endpng" class="endpng" src="img/site/end.png">
</div>
~~~
> fn:substring()函数返回字符串中指定开始和结束索引的子串。意思是取产品名字的前20个字符
>
### 拓展资料: fmt:formatNumber 格式化数字
> fmt 标签常用来进行格式化,其中fmt:formatNumber用于格式化数字
使用之前要加上
`<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix='fmt' %> `
`<fmt:formatNumber type="number" value="${money}" minFractionDigits="2"/>`
<fmt:formatNumber 表示格式化数字
minFractionDigits 小数点至少要有的位数
maxFractionDigits 小数点最多能有的位数
## 步骤 8 : 总结
虽然首页显示的内容非常多,可以说是前端里最复杂的一个展示页面,但是通过这种拆成小块jsp的思路,每个jsp页面的功能就相对单一了。 可以更好的帮助大家理解。
- 项目简介
- 功能一览
- 前台
- 后台
- 开发流程
- 需求分析-展示
- 首页
- 产品页
- 分类页
- 搜索结果页
- 购物车查看页
- 结算页
- 确认支付页
- 支付成功页
- 我的订单页
- 确认收货页
- 确认收货成功页
- 评价页
- 需求分析-交互
- 分类页排序
- 立即购买
- 加入购物车
- 调整订单项数量
- 删除订单项
- 生成订单
- 订单页功能
- 确认付款
- 确认收货
- 提交评价信息
- 登录
- 注册
- 退出
- 搜索
- 前台需求列表
- 需求分析后台
- 分类管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性设置
- 用户管理
- 订单管理
- 后台需求列表
- 表结构设计
- 数据建模
- 表与表之间的关系
- 后台-分类管理
- 可运行的项目
- 静态资源
- JSP包含关系
- 查询
- 分页
- 增加
- 删除
- 编辑
- 修改
- 做一遍
- 重构
- 分页方式
- 分类逆向工程
- 所有逆向工程
- 后台其他页面
- 属性管理实现
- 产品管理实现
- 产品图片管理实现
- 产品属性值设置
- 用户管理实现
- 订单管理实现
- 前端
- 前台-首页
- 可运行的项目
- 静态资源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前台-无需登录
- 注册
- 登录
- 退出
- 产品页
- 模态登录
- 分类页
- 搜索
- 前台-需要登录
- 购物流程
- 立即购买
- 结算页面
- 加入购物车
- 查看购物车页面
- 登录状态拦截器
- 其他拦截器
- 购物车页面操作
- 订单状态图
- 生成订单
- 我的订单页
- 我的订单页操作
- 评价产品
- 总结