目 录CONTENT

文章目录

快递案例localStorage缓存版

Administrator
2020-07-24 / 0 评论 / 0 点赞 / 8597 阅读 / 20810 字

快递案例(localStorage缓存版)

  • 案例名称:快递案例webSql版
  • 案例人员:杨标
  • 案例平台:HTML+CSS+JavasScript+jQuery+template+iconfont+Ajax
  • 完成时间:2019年9月12日

::: tip 提示
本案例可下载
:::


效果图

image.png

image.png

案例说明

本案例旨在对jQuery里面的ajax做一次基础的练习,同时能够了 解get请求的原理,了解URL地址中的请求地址与请求参数的区别

本案例分为两个页面,一个是查询快递的页面,一个是快递查询的历史记录的页面,在历史记录的页面要实现左滑删除,同时点击历史记录以后要跳到查询的页面进行查询

在页面进行跳转的时候,要使用地HTML静态页面的跨页面传值技术,本案例使用的是URLSearchParams这个对象,它是HTML5里面新出的对象,也是现在常用的一种跨页面传值技术

本案例当中的历史记录有两个版本,一个是通过localStorage 的方式进行的存储,一个是通过webSql的方式在进行存储

案例代码

本案例分为两个页面,目录结构如下所示

1568892982370.png

主页功能

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/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 kdHistory = null; //定义一个数组,用于存放历史记录
    $(function () {
        if (localStorage.getItem("kdComList")) {
            kdComList = JSON.parse(localStorage.getItem("kdComList"));
            $("#kdType").renderTpl("kdTypeTemp", {
                kdComList: kdComList
            });
        } else {
            //同学们做的时候,请把快递公司做个缓存
            layer.load(1, {
                shade: [0.1, '#fff'] //0.1透明度的白色背景
            }); //出现加载动画 
            //如果我需要向服务器发送数据,那么我就把数据把在方法里面的第二个参数里在
            $.get("https://www.softeem.xin/Api/KuaiDi/getKuaiDiCom", function (data) {
                //data代表的是服务器返回给我们的数据,它不是固定的,服务器返回的是什么,我们得到的就是什么!
                $("#kdType").renderTpl("kdTypeTemp", {
                    kdComList: data
                });
                kdComList = data;
                layer.closeAll();
                localStorage.setItem("kdComList", JSON.stringify(kdComList));
            });
        }

        //查询事件
        $(".btnQuery").click(function () {
            var type = $("#kdType").val(); //快递类型 ,它是一个key
            var postId = $("#postId").val(); //快递单号,它是一个字符串
            //如果用户没有输入快递单号,则提示框
            if (postId == "") {
                //说明没有输入

                layer.alert("请输入快递单号")
            } else {
                queryKuaiDi(type, postId);
            }

        });

        (function () {
            //我要在这里检测一下,当前这个页面有没有参数给我
            //如果有参数给我,就说明是从历史记录的页面跳过来(获取参数,查询快递),如果没有参数,就是直接打开的
            var searchParams = new URLSearchParams(location.search);
            var postId = searchParams.get("postId");
            var type = searchParams.get("type");
            if (postId && type) {
                queryKuaiDi(type, postId);
            }
        })();
        //查询快递的方法
        function queryKuaiDi(type, postId) {
            //出现加载动画 
            layer.load(1, {
                shade: [0.1, '#fff'] //0.1透明度的白色背景
            });
            //应该是将快递类型与快递单号发送给服务器
            var url = "https://www.softeem.xin/Api/KuaiDi/getKuaiDiInfo?type=" + type + "&postId=" +
                postId;
            $.get(url, function (data) {
                layer.closeAll();
                $(".resultList").renderTpl("resultListTemp", {
                    traces: data.Traces
                });

                //保存历史记录 先讲storage版本
                //1.先看一下有没有缓存kdHistory
                if (localStorage.getItem("kdHistory")) {
                    //说明原来有
                    kdHistory = JSON.parse(localStorage.getItem("kdHistory"));
                } else {
                    //说明没有
                    kdHistory = [];
                }
                //2.去历史记录里面去找,之前我有没有查询过一条这样的快递
                var arr = kdHistory.filter(function (item, index, a) {
                    return item.postId == postId
                });
                if (arr.length > 0) {
                    //存在  把这条记录找出来
                    var currentObj = arr[0]; //这是对象  这是浅拷贝  currentObj改变,arr[0]也改
                    currentObj.time = new Date().toLocaleString(); //把时间换成当前时间
                    currentObj.lastInfo = data.Traces[data.Traces.length - 1].AcceptTime + " " + data
                        .Traces[data.Traces.length - 1].AcceptStation
                    //再放到缓存里面去
                    localStorage.setItem("kdHistory", JSON.stringify(kdHistory));
                } else {
                    //不存在
                    //我们假设没有
                    //是否可以拿快递公司的名称
                    var com = kdComList.filter(function (item, index, a) {
                        return item.key == type;
                    })[0].com;

                    kdHistory.push({
                        time: new Date().toLocaleString(),
                        postId: postId,
                        lastInfo: data.Traces[data.Traces.length - 1].AcceptTime +
                            " " +
                            data.Traces[data.Traces.length - 1].AcceptStation,
                        type: type, //快递公司的编号
                        com: com //快递公司的名称
                    })
                    //再放到缓存里面去
                    localStorage.setItem("kdHistory", JSON.stringify(kdHistory));
                }
            });
        }

    })

    /*
    1.jQuery
    2.移动端布局
    3.Ajax
    4.请求地址与请求参数
    5.学会了看API文档
    6.缓存的练习
    7.跨页面的传值 URLSearchParams
    8.模板引擎的使用
    9.事件委托 的应用场景
    10.layer.js的初步使用
    11.jQuery扩展方法的应用
    12.iconfont的使用       
    13.触摸实现在滑删除
    14.CSS移动端取消高亮,以及下拉框去掉箭头
    15.jQuery的event找到原始事件
    16.JSON的转换 JSON.parse与JSON.stringify
    */
</script>
</html>

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;
}

上面的HTML代码与CSS代码已经可以完成主页的效果了,现在我们再进行历史记录页面的完成功能

历史记录页功能

该页面主要的功能就是将之前的查询记录缓存起来,方便用户以后再次去查询

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/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 = [];
        if (localStorage.getItem("kdHistory")) {
            kdHistory = JSON.parse(localStorage.getItem("kdHistory"));
        }
        //在通过模板引擎去调用
        $(".historyList").renderTpl("historyItemTemp", {
            kdHistory: kdHistory
        });
        //点击历史记录重新查询
        $(".historyList").on("click", ".historyItem", function () {
            //我们要取到快递类型与快递的单号
            var type = $(this).data("type");
            var postId = $(this).data("postid");
            location.href = "index.html?type=" + type + "&postId=" + postId;
            //这是两个页面,涉及到跨页面传值

        });
        var delBtnWidth = $(".delBtn").width();
        //通过链式语法,一次性绑定三个事件
        $(".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 () {
            layer.confirm("你确定要删除这条记录", function (a) {
                //代表用户点击确定  a代表当前弹窗的序号
                layer.close(a);  //关闭当前这个序号的弹窗
                var postId = $(this).prev(".historyItem").data("postid");
                var kdHistory = JSON.parse(localStorage.getItem("kdHistory"));
                var index = kdHistory.map(function (item, index, a) {
                    return item.postId; //返回快递编号
                }).indexOf(postId);
                kdHistory.splice(index, 1);
                //把删除以后的数据重新放回缓存里面去
                localStorage.setItem("kdHistory", JSON.stringify(kdHistory));
                //重新渲染模板
                $(".historyList").renderTpl("historyItemTemp", {
                    kdHistory: kdHistory
                });
            })
        })
    });
</script>
</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;
}

在完成历史记录页的时候,要注意这里面的左滑删除功能 ,该功能是移动端常见的效果功能

案例总结

本案例为基础案例,使用的技术与锻炼的能力有以下几点

  1. jQuery
  2. 移动端布局
  3. Ajax
  4. 请求地址与请求参数
  5. 学会了看API文档
  6. 缓存的练习
  7. 跨页面的传值URLSearchParams
  8. 模板引擎的使用
  9. 事件委托的应用场景
  10. layer.js的初步使用
  11. jQuery扩展方法的应用
  12. iconfont的使用
  13. 触摸实现在滑删除
  14. CSS移动端取消高亮,以及下拉框去掉箭头
  15. jQuery的event找到原始事件
  16. JSON的转换 JSON.parse与JSON.stringify

0

评论区