快递案例webSql版
- 案例名称:快递案例webSql版
- 案例人员:杨标
- 案例平台:HTML+CSS+JavasScript+jQuery+template+iconfont+Ajax
- 完成时间:2019年9月12日
::: tip 提示
本案例可下载
:::
效果图
案例说明
在进行这个案例之前,已经有一个 localStorage
的版本,可自行去查看,该案例与之前的案例相似,只是将缓存的方式改为了webSql。
希望通过该案例能够对一些常用的Sql操作运用于实际的开发案例当中,同时也为后期的mysql做一个预习,如果各们有时间可以将两个案例下载以后自习研究一下,现将代码贴出
案例代码
该案例的目录结构如下图
主页功能
index.html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>快递查询</title>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
document.documentElement.style.fontSize = document.documentElement.clientWidth / 750 * 100 + "px";
})
</script>
<link rel="stylesheet" href="./css/index.css" type="text/css">
<link rel="stylesheet" href="http://at.alicdn.com/t/font_1307637_s4x727lwhxf.css">
<!-- 导入layer插件的css -->
<link rel="stylesheet" href="./js/layer/theme/default/layer.css">
</head>
<body>
<div id="app">
<!--头部的标题-->
<div class="header">快递查询</div>
<!-- 中间的主体 -->
<div class="content">
<div class="formBox">
<select id="kdType">
<option value="">-请选择快递类型-</option>
</select>
<input type="text" id="postId" placeholder="请输入快递单号">
<button type="button" class="btnQuery">查询</button>
</div>
<!--在这里应该有个结果-->
<ul class="resultList"></ul>
</div>
<!-- 下边的tabBar -->
<ul class="tabBar">
<li style="color: deeppink">
<span class="iconfont icon-chaxun"></span>
<span>查询</span>
</li>
<li onclick="location.href='history.html'">
<span class="iconfont icon-wode"></span>
<span>我的</span>
</li>
</ul>
</div>
<template id="kdTypeTemp">
{{each kdComList item index}}
<option value="{{item.key}}">{{item.com}}</option>
{{/each}}
</template>
<template id="resultListTemp">
{{each traces item index}}
<li>
<div class="time">{{item.AcceptTime}}</div>
<div class="state">{{item.AcceptStation}}</div>
</li>
{{/each}}
</template>
</body>
<script src="./js/initDB.js" type="text/javascript"></script>
<script src="./js/jquery.js" type="text/javascript"></script>
<script src="./js/template-web.js" type="text/javascript"></script>
<script src="./js/juqery.extend.js" type="text/javascript"></script>
<script src="./js/layer/layer.js" type="text/javascript"></script>
<script>
var kdComList = []; //用于保存快递信息
var baseURL = "https://www.softeem.xin";
$(function () {
//怎么样判断有没有缓存呢
db.transaction(function (tx) {
tx.executeSql("select * from kdComList", [], function (tx, result) {
if (result.rows.length == 0) {
//没有绑上,请求
$.get(baseURL + "/Api/KuaiDi/getKuaiDiCom", function (data) {
kdComList = data;
db.transaction(function (tx) {
kdComList.forEach(function (item, index, a) {
tx.executeSql("insert into kdComList (key,com) values (?,?)", [item.key, item.com]);
});
})
//渲染模板
$("#kdType").renderTpl("kdTypeTemp", {
kdComList: kdComList
});
});
} else {
//有缓存
kdComList = Array.prototype.slice.call(result.rows);
$("#kdType").renderTpl("kdTypeTemp", {
kdComList: kdComList
});
}
});
});
$(".btnQuery").click(function () {
//获取快递类型与快递单号
var type = $("#kdType").val();
var postId = $("#postId").val();
if (type && postId) {
//现在,这第二个参数代表的是请求参数
//在GET请求的时候,请求地址与请求参数是可以拼在一起的,也可以像下面这种方式来进行分开
//jQuery里面的Ajax会自动将我们的参数进行拼接
$.get(baseURL + "/Api/KuaiDi/getKuaiDiInfo", {
type: type,
postId: postId
}, function (data) {
$(".resultList").renderTpl("resultListTemp", { traces: data.Traces })
//缓存操作
db.transaction(function (tx) {
tx.executeSql("select * from kdHistory where postId=?", [postId], function (tx, result) {
if (result.rows.length == 0) {
//没有找到 添加记录
//先找到com
var com = kdComList.filter(function (item, index, a) {
return item.key == type;
})[0].com;
//获取快递最后一条信息
var lastItem = data.Traces[data.Traces.length - 1];
tx.executeSql("insert into kdHistory (com,type,postId,time,lastInfo) values (?,?,?,?,?)", [com, type, postId, new Date().toLocaleString(), lastItem.AcceptTime + " " + lastItem.AcceptStation]);
}
else {
//找到了 修改记录
var lastItem = data.Traces[data.Traces.length - 1];
tx.executeSql("update kdHistory set time=?,lastInfo=? where postId=?", [new Date().toLocaleString(), lastItem.AcceptTime + " " + lastItem.AcceptStation, postId]);
}
})
})
});
}
else {
layer.alert("请输入快递单号与选择快递公司");
}
});
})
</script>
</html>
在上面的代码过程当中,我们看到有一个initDB.js
这个文件,该文件主要是对webSql做一次初始化,创建webSql数据库与的过程,代码如下
initDB.js代码
var db = openDatabase("bgkuaidi", "1.0", "bgkuaidi", 2 * 1024 * 1024);
//创建一个数据表,用于放快递公司的缓存
db.transaction(function (tx) {
//创建了第一个数据表,用于存放快递公司的缓存
tx.executeSql("CREATE TABLE IF NOT EXISTS kdComList (key,com)");
//创建一个数据表,用于放查询记录
tx.executeSql("CREATE TABLE IF NOT EXISTS kdHistory (com,type,postId,time,lastInfo)");
});
index.css代码
@charset "utf-8";
*{
margin: 0px;
padding: 0px;
list-style-type: none;
/* 取消按钮与a标签点击的时候的高亮效果 */
-webkit-tap-highlight-color: transparent;
}
body{
font-size: 16px;
}
#app{
width:100vw;
height:100vh;
display:flex;
flex-direction: column;
}
.header{
height: .9rem;
background-color: deeppink;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
font-size: .44rem;
}
.content{
flex: 1;
overflow: auto;
background-image: radial-gradient(deeppink,white);
}
.tabBar{
width:100%;
display: flex;
height: 1.1rem;
border-top: 1px solid #ececec;
justify-content: space-around;
}
.tabBar li{
height: inherit;
width: 1.1rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.tabBar li span.iconfont{
font-size: .44rem;
}
.tabBar li span:last-child{
font-size: .24rem;
}
.formBox{
box-sizing: border-box;
padding: .4rem;
}
#kdType,#postId{
width: 100%;
padding: 10px;
margin-top: .2rem;
box-sizing: border-box;
border:none;
/* 去掉下拉框的小箭头 */
-webkit-appearance: none;
}
.btnQuery{
width: 100%;
border: none;
padding: 10px;
background-color: white;
margin-top: .2rem;
cursor: pointer;
box-shadow: 2px 4px 2px red;
outline: none;
}
.btnQuery:active{
transform: translate(2px,4px);
box-shadow: none;
}
.resultList{
padding: .2rem;
font-size: .24rem;
}
.resultList li{
display: flex;
border-radius:2px;
background-color:rgba(255,255,255,0.3);
}
.resultList li .time{
width: 2.2rem;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
position:relative;
padding:0.1rem;
}
.resultList li .time::after{
content:"";
display:block;
position:absolute;
height:100%;
border-right:1px solid #ececec;
right:0px;
}
.resultList li .state{
flex: 1;
display:flex;
align-items:center;
padding:0.1rem;
padding-left:0.25rem;
position:relative;
}
.resultList li .state::before{
content:"";
display:block;
position:absolute;
width:10px;
height:10px;
border-radius:50%;
background-color:lightgray;
left:-5px;
}
.resultList li:first-child .time::after{
height:50%;
top:50%;
}
.resultList li:last-child .time::after{
height:50%;
top:0px
}
.resultList li:first-child .state::before{
background-color:deeppink;
}
.resultList li:first-child{
color:deeppink;
}
历史记录功能
该页面主要的功能就是将之前的查询记录缓存起来,方便用户以后再次去查询
history.html页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>快递查询</title>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
document.documentElement.style.fontSize = document.documentElement.clientWidth / 750 * 100 + "px";
})
</script>
<link rel="stylesheet" href="./css/index.css" type="text/css">
<link rel="stylesheet" href="http://at.alicdn.com/t/font_1307637_s4x727lwhxf.css">
<!-- 导入layer插件的css -->
<link rel="stylesheet" href="./js/layer/theme/default/layer.css">
<link rel="stylesheet" href="./css/history.css">
</head>
<body>
<div id="app">
<!--头部的标题-->
<div class="header">历史记录</div>
<!-- 中间的主体 -->
<div class="content">
<ul class="historyList">
</ul>
</div>
<!-- 下边的tabBar -->
<ul class="tabBar">
<li onclick="location.href='index.html'">
<span class="iconfont icon-chaxun"></span>
<span>查询</span>
</li>
<li style="color:deeppink">
<span class="iconfont icon-wode"></span>
<span>我的</span>
</li>
</ul>
</div>
<template id="historyItemTemp">
{{each kdHistory item index}}
<li>
<div class="historyItem" data-type="{{item.type}}" data-postid="{{item.postId}}">
<div class="top">
<div>
<span>{{item.com}}</span>
<span>{{item.postId}}</span>
</div>
<div>{{item.time}}</div>
</div>
<div class="bottom">{{item.lastInfo}}</div>
</div>
<div class="delBtn">删除</div>
</li>
{{/each}}
</template>
</body>
<script src="./js/initDB.js" type="text/javascript"></script>
<script src="./js/jquery.js" type="text/javascript"></script>
<script src="./js/template-web.js" type="text/javascript"></script>
<script src="./js/juqery.extend.js" type="text/javascript"></script>
<script src="./js/layer/layer.js" type="text/javascript"></script>
<script>
$(function () {
//当页面加载完毕以后,我要去判断缓存时面有没有历史记录
var kdHistory = [];
var delBtnWidth;
db.transaction(function (tx) {
tx.executeSql("select * from kdHistory", [], function (tx, result) {
//类数组转换成数组
kdHistory = Array.prototype.slice.call(result.rows);
//在通过模板引擎去调用
$(".historyList").renderTpl("historyItemTemp", {
kdHistory: kdHistory
});
// 默认情况下是没有按钮的,要经过渲染完成以后才会的,所以代码应该写在这个地方
delBtnWidth = $(".delBtn").width();
})
})
//点击历史记录重新查询
$(".historyList").on("click", ".historyItem", function () {
//我们要取到快递类型与快递的单号
var type = $(this).data("type");
var postId = $(this).data("postid");
location.href = "index.html?type=" + type + "&postId=" + postId;
//这是两个页面,涉及到跨页面传值
});
//通过链式语法,一次性绑定三个事件
$(".historyList").on("touchstart", ".historyItem", function (event) {
//现在要判断一根手指
if (event.originalEvent.changedTouches.length == 1) {
//记录一下手指的横坐标 把这个值记录在自定义属性里面
$(this).attr("data-startx", event.originalEvent.changedTouches[0].clientX);
}
}).on("touchmove", ".historyItem", function (event) {
if (event.originalEvent.changedTouches.length == 1) {
//用当前的坐标-之前触摸开始的坐标
var length = event.originalEvent.changedTouches[0].clientX - parseFloat($(this).attr(
"data-startx"));
//判断向左还是向右
if (length < 0) {
if (Math.abs(length) > delBtnWidth) {
length = delBtnWidth * (-1);
}
//说明向左在滑
$(this).css("left", length + "px");
} else if (length > 0) {
//只要我发现你向右滑
$(this).css("left", "0px");
}
}
}).on("touchend", ".historyItem", function (event) {
if (event.originalEvent.changedTouches.length == 1) {
var length = event.originalEvent.changedTouches[0].clientX - parseFloat($(this).attr(
"data-startx"));
if (length < 0) {
//向左
if (Math.abs(length) > delBtnWidth / 2) {
length = delBtnWidth * (-1);
} else {
length = 0;
}
$(this).css("left", length + "px");
} else if (length > 0) {
//向右
$(this).css("left", "0px");
}
}
});
//绑定左滑以后的删除按钮事件
$(".historyList").on("click", ".delBtn", function () {
var that=this;
layer.confirm("你确定要删除这条记录", function (a) {
//代表用户点击确定 a代表当前弹窗的序号
layer.close(a); //关闭当前这个序号的弹窗
var postId = $(that).prev(".historyItem").data("postid");
db.transaction(function(tx){
tx.executeSql("delete from kdHistory where postId=?",[postId.toString()],function(tx,result){
location.reload();
});
});
})
});
});
</script>
<!--
1.webSql的使用,重温SQL语句
2.Ajax请求的参数可以使用对象的方式来进行,jQuery自动帮我们拼接【GET请求】
对象这种情况下面的参数是既可以在GET下面使用,也可以在POST下面使用
$.get(url,{},function(data){})
$.get(url?请求参数,function(data){});
$.post(url,{},function(data){}); //POST如果有参数,只能这么写
3.注意this的情况,注意页面加载的情况
通过模板生成的DOM,你应该是先等模板生成完了以后,再进行这些DOM操作
-->
</html>
history.css代码
@charset "utf-8";
.historyList{
background-color: white;
}
.historyList li{
border-bottom: 1px solid #ececec;
background-color:white;
position:relative;
}
.historyList li .historyItem .top{
display: flex;
font-size: .24rem;
justify-content: space-between;
}
.historyList li .historyItem .bottom{
font-size: .28rem;
margin-top: .2rem;
}
.historyList li .historyItem .top span:first-child{
font-weight:bold;
}
/*删除按钮怎么做*/
.delBtn{
background-color:red;
width: 1.2rem;
position: absolute;
right:0px;
top:0px;
height:100%;
display:flex;
justify-content:center;
align-items:center;
color:white;
font-size:.28rem;
/* z-index:-1; */
}
.historyItem{
padding: .2rem;
background-color: white;
position: relative;
z-index: 1;
transition: all 0.1s linear;
}
案例总结
本案例为基础案例,与之前的localStorage版本相对比,主要的学习点在以下几个方面
-
webSql的使用,重温SQL语句
-
Ajax请求的参数可以使用对象的方式来进行,jQuery自动帮我们拼接【GET请求】
对象这种情况下面的参数是既可以在GET下面使用,也可以在POST下面使用
$.get(url,{},function(data){})
$.get(url?请求参数,function(data){});
$.post(url,{},function(data){});
//POST如果有参数,只能这么写 -
注意this的情况,注意页面加载的情况
通过模板生成的DOM,你应该是先等模板生成完了以后,再进行这些DOM操作
总之,两个版本都是做的同一个案例,其中80%的代码是相同的,但是有些地方换了一种方式再写,各个可以仔细对象一下,特别是在缓存操作webSql以及Ajax请求的时候