效果图
首先是目录结构
menu.html
<!DOCTYPE html> <html lang="en"head> meta charset="UTF-8"title>menu</name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"script> (function(){ //这段代码放在所有的样式文件之前,设置html根元素的fontSize var docEl=document.documentElement; setRem(){ 这个10不是固定的,只是计算出来的rem要和cssrem插件setting中设置的37.5保持一致 iphone6设备宽度是375,因此基准值刚好是10 remdocEl.clientWidth/10;获取基准值 docEl.style.fontSizerem+"px;动态设置html根元素的fontSize } setRem(); window.addEventListener(resize,setRem); 用户每次浏览页面的时候, 就会触发pagesshow方法(有兼容性问题) window.addEventListener(pageshow(e){ 使用e.presisted就是判断当前页面是不是在缓存中加载 如果缓存中加载(就是为true的时候),重新设置rem if(e.persisted){ setRem(); } }); })(); link rel="stylesheet" href="../lib/reset.css"><!-- 拷贝一份通用重置样式 --> ="menu.css"="../common/common.css"body 头部开始 div class="nav"> ="back-icon"></divh4 ="title">深圳麦当劳前海二餐厅h4 头部结束 --> tab开始 ="tab-bar" tab结束 点菜内容开始 ="menu-inner" 左侧tab --> ="left-bar"> ="left-bar-inner" 右侧商品 ="right-content"p ="right-title"p="right-list"> ="right-list-inner" 购物车 ="shop-bar" 遮罩 ="mask hide" 点菜内容结束 script src="../lib/jquery.min.js"="menu.js"="../common/common.js"html>
menu.css
/*header-tab*/ .tab-bar{ font-size:0.426667rem; display:flex; border-bottom:0.026667rem solid #f0f0f0; margin-top:1.706667rem; } .tab-bar .tab-item{ flex:1; height:1.2rem; line-height: position: relative; color:#666; text-align:center; text-decoration: none; } .tab-bar .tab-item.active::after{ content:""; block; absolute; width:1.6rem;0.106667rem; bottom:0; background:#ffd161;美团黄*/ 设置居中*/ left:50%; -webkit-transform:translateX(-50%); transform:translateX(-50%); } menu-inner .menu-inner{ top:2.933333rem; right: flex; overflow:hidden; } .menu-inner .left-bar{2.266667rem;#efefef;auto;100%; -webkit-overflow-scrolling:touch;局部滚动,尤其是移动端ios*/ } .menu-inner .left-bar-inner{ padding-bottom:2.266667rem; } .menu-inner .left-item{0.373333rem;#656565;0.026667rem solid #bfbfbf; justify-content: center;1.6rem; } .menu-inner .left-item.active{#fff; } .menu-inner .item-text{ align-self:center; } .menu-inner .item-icon{0.533333rem; inline-block; margin-right:0.16rem; vertical-align:-0.106667rem; } .menu-inner .right-content{ margin-left:0.266667rem;hidden;触屏滚动 .menu-inner .right-title{0.346667rem;#333; padding-left: border-left:0.053333rem solid #ffd161; } .menu-inner .right-list{auto;可滚动 .menu-inner .right-list-inner{ .right-list-inner .menu-item{ padding:0.666667rem 0; relative; } .right-list-inner .img{1.653333rem;0.266667rem; } .right-list-inner .menu-item-right{1; } .right-list-inner .item-title{#2f2f2f; } .right-list-inner .item-desc,.right-list-inner .item-zan{#a9a9a9;0.32rem; padding-right:0.106667rem; } .right-list-inner .item-desc{0.453333rem; } .right-list-inner .item-price{#fe4d3d;0.48rem; } .right-list-inner .unit{0.32rem; } .right-list-inner .select-content{0.24rem;0.56rem; flex; } .right-list-inner .minus{0.666667rem; background-image:url(images/minus.png); background-size:cover; } .right-list-inner .count{0.4rem;#2f2f2f; margin:0 0.053333rem; .right-list-inner .plus{url(images/plus.png);cover; } shopbar .shop-bar{ z-index:99; } .shop-bar .choose-content{ .shop-bar .content-top{0.933333rem; background-color:#f4f4f4;0.293333rem; align-items: flex-end; } .shop-bar .clear-car{0 0.133333rem 0 0.266667rem; .shop-bar .clear-car::after{url(images/clear.jpeg); background-size:cover;-0.026667rem;-0.373333rem; } .shop-bar .bottom-content{1.333333rem;rgba(51,51,.9); } .shop-bar .shop-icon{1.466667rem;url(images/shop-icon.png);-0.4rem; .shop-bar .dot-num{ #fb4e44;#fff; border:0.026667rem solid #fff; border-radius:0.053333rem;0.4rem; } .shop-bar .price-content{ padding-top:0.213333rem;0.186667rem; } .shop-bar .total-price{ .shop-bar .total-price-span{ } .shop-bar .other-price{#999;0.053333rem; } .shop-bar .shipping-fee{ } .shop-bar .submit-btn{#ffd161; .choose-item{0.266667rem 0;0.026667rem solid #ddd; } .choose-item .item-name{ .choose-item .price{0 0.666667rem 0 0.133333rem; } .choose-item .total{ } .choose-item .select-content{ .choose-item .minus{ .choose-item .plus{ .choose-item .count{ .menu-inner .mask{ fixed; rgba(0,.7); }
menu.js
(function(){ //加载左侧类目 initLeftBar(){ 左侧类目的模板字符串 var itemTpl='<div class="left-item">'+ '<div class="item-text">$getItemContent</div>'+ '</div>'; var itemHtml=""var page=0;当前页 var isLoading=false;当前是否处于加载中 获取列表数据 getList(){ page++; isLoading=true; $.get("../json/food.json",(data){ var list=data.data.food_spu_tags || []; window.food_spu_tags=list;把数据挂载到window对象上,方便其他模块调用 list.forEach((item,index){ var str=itemTpl.replace("$getItemContent"var $target=$(str); 将item数据挂载到left-item上面 $target.data("itemData").append($target); }) $(".left-item").first().click();默认显示第一个tab isLoading=false; window.shopBar.changeShippingPrice(data.data.poi_info.shipping_fee || 0);更新价格 }) 关于图标的处理 getItemContent(data){ if(data.icon){ return '<img class="item-icon" src='+data.icon+'>'+data.name; }else{ return data.name; } } } getList();默认先请求一次 滚动加载 window.addEventListener("scroll",1)">(){ var clientHeight=document.documentElement.clientHeight;视窗高度 var scrollHeight=document.body.scrollHeight;body滚动过的总长 var scrollTop=document.documentElement.scrollTop || document.body.scrollTop;body滚动过的总长 var preDis=30;提前的预值 if((scrollTop+clientHeight)>=(scrollHeight-preDis)){ 自定义页面,一次最多滚动3页 if(page<3){ if(isLoading) ; getList(); }{ $(".loading").text("加载完成"); } } }); 左侧tab点击事件 $(".menu-inner").on("click",".left-item",1)">(e){ $(e.currentTarget); 添加点击样式 $target.addClass("active"); $target.siblings().removeClass("active"); 将数据传给右侧详情列表 initRightContent($target.data("itemData"));加载右侧商品 }) } 加载右侧商品 initRightContent(data){ 右侧商品的模板字符串 var itemTpl='<div class="menu-item">'+ '<img src=$picture class="img">'+ '<div class="menu-item-right">'+ '<p class="item-title">$name</p>'+ '<p class="item-desc">$description</p>'+ '<p class="item-zan">$praise_content</p>'+ '<p class="item-price">¥$min_price<span class="unit">/$unit</span></p>'+ '</div>'+ '<div class="select-content">'+ '<div class="minus"></div>'+ '<div class="count">$chooseCount</div>'+ '<div class="plus"></div>'+ '</div>'+ '</div>'; $(".right-list-inner").html(""); var list=data.spus || []; list.forEach(默认为0 if(!item.chooseCount){ item.chooseCount=0; } var str=itemTpl .replace("$picture"$(str); $target.data("itemData",item);把数据挂载在data属性上,方便以后获取 $(".right-list-inner").append($target); }); 右侧顶部title $(".right-title").text(data.name); 加号事件 $(".menu-item").on("click",".plus",1)">var $count=$(e.currentTarget).parent("").find(".count"); $count.text(parseInt($count.text()||"0")+1更新挂载的数据 var $item=$(e.currentTarget).parents(".menu-item").first(); var itemData=$item.data("itemData"); itemData.chooseCount++; window.shopBar.renderItems();购物车渲染 }) 减号事件 $(".menu-item").on("click",".minus",1)">); if($count.text()==0) ; $count.text(parseInt($count.text()||"0")-1); itemData.chooseCount-- }) } shopbar initShopBar(){ shopbar的购物车上部分模板字符串 var itemTopTpl='<div class="choose-content hide">'+ '<div class="content-top">'+ '<div class="clear-car">清空购物车</div>'+ '</div>'+ '</div>'; shopbar的购物车下部分模板字符串 var itemBottomTpl='<div class="bottom-content">'+ '<div class="shop-icon">'+ '<div class="dot-num hide"></div>'+ '</div>'+ '<div class="price-content">'+ '<p class="total-price">¥<span class="total-price-span">0</span></p>'+ '<p class="other-price">另需配送 ¥<span class="shipping-fee">0</span></p>'+ '</div>'+ '<div class="submit-btn">去结算</div>'+ '</div>'var $strTop=$(itemTopTpl); var $strBottom=$(itemBottomTpl); $(".shop-bar").append($strTop); $(".shop-bar").append($strBottom); 渲染购物车数据 renderItems(){ $strTop.find(".choose-item").remove();每次操作之后先全部清空购物车 var list=window.food_spu_tags || []; var totalPrice=0; var tpl='<div class="choose-item">'+ '<div class="item-name">$name</div>'+ '<div class="price">¥<span class="total">$price</span></div>'+ '<div class="select-content">'+ '<div class="minus"></div>'+ '<div class="count">$chooseCount</div>'+ '<div class="plus"></div>'+ '</div>'+ '</div>'; list.forEach((item){ item.spus.forEach((_item){ if(_item.chooseCount>0){ var price=_item.chooseCount*_item.min_price; var row=tpl.replace("$name"总价 .replace("$chooseCount"price; 挂载数据 var $row=$(row); $row.data("itemData"更新总价 changeDot();更新红点 }) } window.shopBar.renderItems=renderItems;将该方法暴露到全局 更新单商品总价 changeShippingPrice(str){ $strBottom.find(".shipping-fee").text(str); } window.shopBar.changeShippingPrice=changeShippingPrice; 更新全商品总价 changeAllPrice(str){ $strBottom.find(".total-price-span").text(str); } window.shopBar.changeAllPrice=changeAllPrice; 购物车里的加号事件 $strTop.on("click",1)">var $item=$(e.currentTarget).parents(".choose-item"); itemData.chooseCount++;更新挂载数据,在列表里也会同步更新 window.shopBar.renderItems();购物车渲染 找到当前右侧详情的数据,进行联动 $(".left-item.active").click(); }) 购物车里的减号事件 $strTop.on("click",1)">); itemData.chooseCount--;点击显示或者隐藏购物车 $(".shop-icon").on("click",1)">(){ $(".mask").toggle(); $strTop.toggle(); }) 计算红点中的数量 changeDot(){ var counts=$strTop.find(".count"var total=0; for(var i=0;i<counts.length;i++){ total+=parseInt($(counts[i]).text()); } if(total>0){ $(".dot-num").show().text(total); }{ $(".dot-num").hide(); } } } 暴露出来的方法 window.shopBar={}; init(data){ initLeftBar();加载左侧类目 initShopBar();加载购物车 } init(); })();
common.css
(加载底部菜单
initBottomBar(){
底部菜单的模板字符串
var itemTpl='<a class="$key btn-item" href="../$key/$key.html">'+
'<div class="tab-icon"></div>'+
'<div class="btn-name">$text</div>'+
'</a>'var items=[{
key:"index"
},{
key:"order"
}];
var str="";
items.forEach((item){
str+=itemTpl.replace(/\$key/g,item.key)正则解决全局替换的问题
.replace("$text").append(str);
判断当前属于哪个页面
var arr=window.location.pathname.split("/");
var page=arr[arr.length-1].replace(".html","");最后一个元素,去掉.html
page=page==""?"index":page;默认显示首页
$("a.btn-item").removeClass("active");
$("a."+page).addClass("active");
}
加载menu页的头部
initTabBar(){
menu页的模板字符串
var itemTpl='<a class="$key tab-item" href="../$key/$key.html">'+
'$text'+
'</a>'[{
key:"menu"最后一个元素,去掉.html
$("a."+page).addClass("active");
}
init(){
initBottomBar();加载底部菜单
initTabBar();加载menu页的头部
}
init();
})();
food.json
太多了放不上来,大家自己琢磨吧==
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。