how2j.cn


5分23秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)

步骤 1 : HTML 包含技术   
步骤 2 : 分类查询对应的HTML文件   
步骤 3 : adminHeader.html   
步骤 4 : adminNavigator.html   
步骤 5 : adminPage.html   
步骤 6 : adminFooter.html   

步骤 1 :

HTML 包含技术

Html 本身不是能够直接包含其他的 Html 文件的,但是一个项目里又有很多可以共用的部分。 那么就会采用 Thymeleaf 的包含技术把这些共用部分拼接起来。
而Thymeleaf 支持纯 html ,这样即能使用 单纯的html ,又可以享受到包含的好处了。

相关学习教程: Thymeleaf 系列教程 , Thymeleaf 如何进行包含
步骤 2 :

分类查询对应的HTML文件

分类查询对应的HTML文件是listCategory.html,但是本知识点不讲解listCategory.html本身,而是讲解其所包含的几个公共的 html 文件。
listCategory.html本身留在分类管理-查询讲解。

listCategory.html 用到了4个公共包含文件
1. <%@include file="../include/admin/adminHeader.html"%>
2. <%@include file="../include/admin/adminNavigator.html"%>
3. <%@include file="../include/admin/adminPage.html"%>
4. <%@include file="../include/admin/adminFooter.html"%>
分类查询对应的HTML文件
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:include="include/admin/adminHeader::html('分类管理')" ></head> <body> <div th:replace="include/admin/adminNavigator::html" ></div> <script> $(function(){ var data4Vue = { uri:'categories', beans: [], bean: { id: 0, name: ''}, pagination:{}, file: null }; //ViewModel var vue = new Vue({ el: '#workingArea', data: data4Vue, mounted:function(){ //mounted 表示这个 Vue 对象加载成功了 this.list(0); }, methods: { list:function(start){ var url = this.uri+ "?start="+start; axios.get(url).then(function(response) { vue.pagination = response.data; vue.beans = response.data.content ; }); }, add: function () { if(!checkEmpty(this.bean.name, "分类名称")) return; if(!checkEmpty(this.file, "分类图片")) return; var url = this.uri; //axios.js 上传文件要用 formData 这种方式 var formData = new FormData(); formData.append("image", this.file); formData.append("name", this.bean.name); axios.post(url,formData).then(function(response){ vue.list(0); vue.bean = { id: 0, name: '', hp: '0'}; $("#categoryPic").val(''); vue.file = null; }); }, deleteBean: function (id) { if(!checkDeleteLink()) return; var url = this.uri+"/"+id; axios.delete(url).then(function(response){ if(0!=response.data.length){ alert(response.data); } else{ vue.list(0); } }); }, getFile: function (event) { this.file = event.target.files[0]; }, jump: function(page){ jump(page,vue); //定义在adminHeader.html 中 }, jumpByNumber: function(start){ jumpByNumber(start,vue); } } }); }); </script> <div id="workingArea" > <h1 class="label label-info" >分类管理</h1> <br> <br> <div class="listDataTableDiv"> <table class="table table-striped table-bordered table-hover table-condensed"> <thead> <tr class="success"> <th>ID</th> <th>图片</th> <th>分类名称</th> <th>属性管理</th> <th>产品管理</th> <th>编辑</th> <th>删除</th> </tr> </thead> <tbody> <tr v-for="bean in beans "> <td>{{bean.id}}</td> <td> <img height="40px" :src="'img/category/'+bean.id+'.jpg'"> </td> <td> {{bean.name}} </td> <td> <a :href="'admin_property_list?cid=' + bean.id "><span class="glyphicon glyphicon-th-list"></span></a> </td> <td> <a :href="'admin_product_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a> </td> <td> <a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a> </td> <td> <a href="#nowhere" @click="deleteBean(bean.id)"><span class=" glyphicon glyphicon-trash"></span></a> </td> </tr> </tbody> </table> </div> <div th:replace="include/admin/adminPage::html" ></div> <div class="panel panel-warning addDiv"> <div class="panel-heading">新增分类</div> <div class="panel-body"> <table class="addTable"> <tr> <td>分类名称</td> <td><input @keyup.enter="add" v-model.trim="bean.name" type="text" class="form-control"></td> </tr> <tr> <td>分类图片</td> <td> <input id="categoryPic" accept="image/*" type="file" name="image" @change="getFile($event)" /> </td> </tr> <tr class="submitTR"> <td colspan="2" align="center"> <a href="#nowhere" @click="add" class="btn btn-success">提交</a> </td> </tr> </table> </div> </div> </div> <div th:replace="include/admin/adminFooter::html" ></div> </body> </html>
步骤 3 :

adminHeader.html

每个后台页面都在一开始使用了adminHeader.html
1. <template th:fragment="html(title)" >
表示本页面可以通过 adminHeader::html 方式包含。 而且包含的时候可以传递 title 参数 进来

2. 用到的一系列的 js 和 css 文件

<script src="js/jquery/2.0.0/jquery.min.js"></script>
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<script src="js/vue/2.5.16/vue.min.js"></script>
<script src="js/axios/0.17.1/axios.min.js"></script>
<script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 -->
<link href="css/back/style.css" rel="stylesheet">

3. 各种自定义函数,这些函数都会在后台管理页面上用到

//判断是否为空
function checkEmpty(value,text){

if(null==value || value.length==0){
alert(text+ "不能为空");
return false;
}
return true;
}

//获取地址栏参数的函数
function getUrlParms(para){
var search=location.search; //页面URL的查询部分字符串
var arrPara=new Array(); //参数数组。数组单项为包含参数名和参数值的字符串,如“para=value”
var arrVal=new Array(); //参数值数组。用于存储查找到的参数值

if(search!=""){
var index=0;
search=search.substr(1); //去除开头的“?”
arrPara=search.split("&");

for(i in arrPara){
var paraPre=para+"="; //参数前缀。即参数名+“=”,如“para=”
if(arrPara[i].indexOf(paraPre)==0&& paraPre.length<arrPara[i].length){
arrVal[index]=decodeURI(arrPara[i].substr(paraPre.length)); //顺带URI解码避免出现乱码
index++;
}
}
}

if(arrVal.length==1){
return arrVal[0];
}else if(arrVal.length==0){
return null;
}else{
return arrVal;
}
}

//判断是否数字 (小数和整数)
function checkNumber(value, text){

if(value.length==0){
alert(text+ "不能为空");
return false;
}
if(isNaN(value)){
alert(text+ "必须是数字");
return false;
}
return true;
}
//判断是否整数
function checkInt(value, text){

if(value.length==0){
alert(text+ "不能为空");
return false;
}
if(parseInt(value)!=value){
alert(text+ "必须是整数");
return false;
}
return true;
}

//确实是否要删除
function checkDeleteLink(){
var confirmDelete = confirm("确认要删除");
if(confirmDelete)
return true;
return false;
}
//分页跳转函数,向前跳或者向后跳,或者跳转到第一页或者最后一页。
function jump(page,vue){
if('first'== page && !vue.pagination.first)
vue.list(0);

else if('pre'== page && vue.pagination.hasPrevious )
vue.list(vue.pagination.number-1);

else if('next'== page && vue.pagination.hasNext)
vue.list(vue.pagination.number+1);

else if('last'== page && !vue.pagination.last)
vue.list(vue.pagination.totalPages-1);
}
//分页跳转函数,跳转到指定页
function jumpByNumber(start,vue){
if(start!=vue.pagination.number)
vue.list(start);
}

4. 把传递进来的 title 参数显示在 title 元素里

<title th:text="${title}" ></title>
<template th:fragment="html(title)" > <script src="js/jquery/2.0.0/jquery.min.js"></script> <link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet"> <script src="js/bootstrap/3.3.6/bootstrap.min.js"></script> <script src="js/vue/2.5.16/vue.min.js"></script> <script src="js/axios/0.17.1/axios.min.js"></script> <script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 --> <link href="css/back/style.css" rel="stylesheet"> <script> //判断是否为空 function checkEmpty(value,text){ if(null==value || value.length==0){ alert(text+ "不能为空"); return false; } return true; } //获取地址栏参数的函数 function getUrlParms(para){ var search=location.search; //页面URL的查询部分字符串 var arrPara=new Array(); //参数数组。数组单项为包含参数名和参数值的字符串,如“para=value” var arrVal=new Array(); //参数值数组。用于存储查找到的参数值 if(search!=""){ var index=0; search=search.substr(1); //去除开头的“?” arrPara=search.split("&"); for(i in arrPara){ var paraPre=para+"="; //参数前缀。即参数名+“=”,如“para=” if(arrPara[i].indexOf(paraPre)==0&& paraPre.length<arrPara[i].length){ arrVal[index]=decodeURI(arrPara[i].substr(paraPre.length)); //顺带URI解码避免出现乱码 index++; } } } if(arrVal.length==1){ return arrVal[0]; }else if(arrVal.length==0){ return null; }else{ return arrVal; } } //判断是否数字 (小数和整数) function checkNumber(value, text){ if(value.length==0){ alert(text+ "不能为空"); return false; } if(isNaN(value)){ alert(text+ "必须是数字"); return false; } return true; } //判断是否整数 function checkInt(value, text){ if(value.length==0){ alert(text+ "不能为空"); return false; } if(parseInt(value)!=value){ alert(text+ "必须是整数"); return false; } return true; } //确实是否要删除 function checkDeleteLink(){ var confirmDelete = confirm("确认要删除"); if(confirmDelete) return true; return false; } //分页跳转函数,向前跳或者向后跳,或者跳转到第一页或者最后一页。 function jump(page,vue){ if('first'== page && !vue.pagination.first) vue.list(0); else if('pre'== page && vue.pagination.hasPrevious ) vue.list(vue.pagination.number-1); else if('next'== page && vue.pagination.hasNext) vue.list(vue.pagination.number+1); else if('last'== page && !vue.pagination.last) vue.list(vue.pagination.totalPages-1); } //分页跳转函数,跳转到指定页 function jumpByNumber(start,vue){ if(start!=vue.pagination.number) vue.list(start); } </script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title th:text="${title}" ></title> </template>
步骤 4 :

adminNavigator.html

adminNavigator.html
<div class="navitagorDiv" th:fragment="html"> <nav class="navbar navbar-default navbar-fixed-top navbar-inverse"> <img style="margin-left:10px;margin-right:0px" class="pull-left" src="img/site/tmallbuy.png" height="45px"> <a class="navbar-brand" href="#nowhere">天猫后台</a> <a class="navbar-brand" href="admin_category_list">分类管理</a> <a class="navbar-brand" href="admin_user_list">用户管理</a> <a class="navbar-brand" href="admin_order_list">订单管理</a> </nav> </div>
<div class="navitagorDiv" th:fragment="html">
	<nav class="navbar navbar-default navbar-fixed-top navbar-inverse">
		<img style="margin-left:10px;margin-right:0px" class="pull-left" src="img/site/tmallbuy.png" height="45px">
		<a class="navbar-brand" href="#nowhere">天猫后台</a>
		
		<a class="navbar-brand" href="admin_category_list">分类管理</a>
		<a class="navbar-brand" href="admin_user_list">用户管理</a>
		<a class="navbar-brand" href="admin_order_list">订单管理</a>
	</nav>
</div>
步骤 5 :

adminPage.html

这是分页HTML。
分页功能不仅仅有前端效果,还需要结合服务端传递过来的数据综合才能起作用。 所以对于adminPage.html不在此展开讲解,将在后面的分页部分,结合服务端,专门讲解.
adminPage.html
<div class="pageDiv" th:fragment="html"> <nav> <ul class="pagination"> <li :class="{ disabled: pagination.first }"> <a href="#nowhere" @click="jump('first')">«</a> </li> <li :class="{ disabled: !pagination.hasPrevious }"> <a href="#nowhere" @click="jump('pre')">‹</a> </li> <li v-for="i in pagination.navigatepageNums"> <a href="#nowhere" @click="jumpByNumber(i-1)" > {{i}} </a> </li> <li :class="{ disabled: !pagination.hasNext }"> <a href="#nowhere" @click="jump('next')">›</a> </li> <li :class="{ disabled: pagination.last }"> <a href="#nowhere" @click="jump('last')"> »</a> </li> </ul> </nav> </div>
步骤 6 :

adminFooter.html

页脚部分,目前是留白。 大家掌握了之后,可以写自己的名字@myname, 年份,版本信息什么的。
<div th:fragment="html"> <!-- 模仿天猫整站 springboot 教程 为how2j.cn 版权所有--> <!-- 本教程仅用于学习使用,切勿用于非法用途,由此引起一切后果与本站无关--> <!-- 供购买者学习,请勿私自传播,否则自行承担相关法律责任--> </div>
<div th:fragment="html">
	<!-- 模仿天猫整站 springboot 教程 为how2j.cn 版权所有-->
	<!-- 本教程仅用于学习使用,切勿用于非法用途,由此引起一切后果与本站无关-->
	<!-- 供购买者学习,请勿私自传播,否则自行承担相关法律责任-->
</div>


HOW2J公众号,关注后实时获知布最新的教程和优惠活动,谢谢。


提问之前请登陆
关于 实践项目-天猫整站Springboot-HTML 包含关系 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 902680467
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: http://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图