仿美团--详情页与购物车开发
程序员文章站
2022-04-16 09:25:15
效果图 首先是目录结构 menu.html menu
效果图
首先是目录结构
menu.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>menu</title> <meta 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; function setrem(){ // 这个10不是固定的,只是计算出来的rem要和cssrem插件setting中设置的37.5保持一致 // iphone6设备宽度是375,因此基准值刚好是10 var rem=docel.clientwidth/10;//获取基准值 docel.style.fontsize=rem+"px";//动态设置html根元素的fontsize } setrem(); window.addeventlistener("resize",setrem); //用户每次浏览页面的时候, 就会触发pagesshow方法(有兼容性问题) window.addeventlistener("pageshow",function(e){ // 使用e.presisted就是判断当前页面是不是在缓存中加载 // 如果缓存中加载(就是为true的时候),重新设置rem if(e.persisted){ setrem(); } }); })(); </script> <link rel="stylesheet" href="../lib/reset.css"><!-- 拷贝一份通用重置样式 --> <link rel="stylesheet" href="menu.css"> <link rel="stylesheet" href="../common/common.css"> </head> <body> <!-- 头部开始 --> <div class="nav"> <div class="back-icon"></div> <h4 class="title">深圳麦当劳前海二餐厅</h4> </div> <!-- 头部结束 --> <!-- tab开始 --> <div class="tab-bar"></div> <!-- tab结束 --> <!-- 点菜内容开始 --> <div class="menu-inner"> <!-- 左侧tab --> <div class="left-bar"> <div class="left-bar-inner"></div> </div> <!-- 右侧商品 --> <div class="right-content"> <p class="right-title"></p> <div class="right-list"> <div class="right-list-inner"></div> </div> </div> <!-- 购物车 --> <div class="shop-bar"></div> <!-- 遮罩 --> <div class="mask hide"></div> </div> <!-- 点菜内容结束 --> <script src="../lib/jquery.min.js"></script> <script src="menu.js"></script> <script src="../common/common.js"></script> </body> </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:1.2rem; position: relative; color:#666; text-align:center; text-decoration: none; } .tab-bar .tab-item.active::after{ content:""; display: block; position: absolute; width:1.6rem; height:0.106667rem; bottom:0; background:#ffd161;/*美团黄*/ /*设置居中*/ left:50%; -webkit-transform:translatex(-50%); transform:translatex(-50%); } /*menu-inner*/ .menu-inner{ position: absolute; top:2.933333rem; left:0; right:0; bottom:0; display: flex; overflow:hidden; } .menu-inner .left-bar{ width:2.266667rem; background:#efefef; overflow:auto; height:100%; -webkit-overflow-scrolling:touch;/*局部滚动,尤其是移动端ios*/ } .menu-inner .left-bar-inner{ padding-bottom:2.266667rem; } .menu-inner .left-item{ font-size:0.373333rem; color:#656565; text-align:center; border-bottom:0.026667rem solid #bfbfbf; display: flex; justify-content: center; height:1.6rem; } .menu-inner .left-item.active{ background:#fff; } .menu-inner .item-text{ text-align:center; align-self:center; } .menu-inner .item-icon{ width:0.533333rem; height:0.533333rem; display: inline-block; margin-right:0.16rem; vertical-align:-0.106667rem; } .menu-inner .right-content{ flex:1; margin-left:0.266667rem; height:100%; overflow:hidden; -webkit-overflow-scrolling:touch;/*触屏滚动*/ } .menu-inner .right-title{ font-size:0.346667rem; color:#333; margin-top:0.266667rem; padding-left:0.106667rem; border-left:0.053333rem solid #ffd161; } .menu-inner .right-list{ height:100%; overflow:auto;/*可滚动*/ } .menu-inner .right-list-inner{ font-size:0.426667rem; padding-bottom:2.266667rem; } .right-list-inner .menu-item{ display: flex; padding:0.666667rem 0; border-bottom:0.026667rem solid #f0f0f0; position: relative; } .right-list-inner .img{ width:1.653333rem; height:1.653333rem; margin-right:0.266667rem; } .right-list-inner .menu-item-right{ flex:1; } .right-list-inner .item-title{ font-size:0.426667rem; color:#2f2f2f; } .right-list-inner .item-desc, .right-list-inner .item-zan{ color:#a9a9a9; font-size:0.32rem; margin-top:0.16rem; line-height:0.373333rem; padding-right:0.106667rem; } .right-list-inner .item-desc{ line-height:0.453333rem; } .right-list-inner .item-price{ margin-top:0.266667rem; color:#fe4d3d; font-size:0.48rem; } .right-list-inner .unit{ color:#a9a9a9; font-size:0.32rem; } .right-list-inner .select-content{ position: absolute; right:0.24rem; bottom:0.56rem; display: flex; } .right-list-inner .minus{ width:0.666667rem; height:0.666667rem; background-image:url(images/minus.png); background-size:cover; } .right-list-inner .count{ font-size:0.4rem; color:#2f2f2f; width:0.666667rem; height:0.666667rem; line-height:0.666667rem; margin:0 0.053333rem; text-align:center; } .right-list-inner .plus{ width:0.666667rem; height:0.666667rem; background-image:url(images/plus.png); background-size:cover; } /*shopbar*/ .shop-bar{ position: absolute; bottom:0; left:0; right:0; z-index:99; } .shop-bar .choose-content{ background:#fff; } .shop-bar .content-top{ height:0.933333rem; background-color:#f4f4f4; font-size:0.293333rem; display: flex; align-items: center; justify-content: flex-end; } .shop-bar .clear-car{ margin:0 0.133333rem 0 0.266667rem; position: relative; } .shop-bar .clear-car::after{ content:""; width:0.346667rem; height:0.346667rem; display: block; background-image:url(images/clear.jpeg); background-size:cover; position: absolute; top:-0.026667rem; left:-0.373333rem; } .shop-bar .bottom-content{ height:1.333333rem; display: flex; background:rgba(51,51,51,.9); } .shop-bar .shop-icon{ width:1.466667rem; height:1.466667rem; background-image:url(images/shop-icon.png); background-size:cover; margin-top:-0.4rem; margin-left:0.32rem; position: relative; } .shop-bar .dot-num{ position: absolute; background-color: #fb4e44; width:0.4rem; height:0.4rem; font-size:0.32rem; color:#fff; border:0.026667rem solid #fff; border-radius:50%; right:0; top:0.053333rem; text-align: center; line-height:0.4rem; } .shop-bar .price-content{ flex:1; padding-top:0.213333rem; padding-left:0.186667rem; } .shop-bar .total-price{ font-size:0.533333rem; color:#fff; } .shop-bar .total-price-span{ } .shop-bar .other-price{ font-size:0.32rem; color:#999; margin-top:0.053333rem; } .shop-bar .shipping-fee{ } .shop-bar .submit-btn{ width:2.933333rem; height:100%; background:#ffd161; color:#333; font-size:0.426667rem; line-height:1.333333rem; text-align:center; } .choose-item{ display: flex; font-size:0.4rem; color:#2f2f2f; height:0.933333rem; align-items: center; padding:0.266667rem 0; border-bottom:0.026667rem solid #ddd; } .choose-item .item-name{ flex:1; padding-left:0.266667rem; } .choose-item .price{ margin:0 0.666667rem 0 0.133333rem; } .choose-item .total{ } .choose-item .select-content{ position: relative; margin-right:0.213333rem; display: flex; } .choose-item .minus{ width:0.666667rem; height:0.666667rem; background-image:url(images/minus.png); background-size:cover; } .choose-item .plus{ width:0.666667rem; height:0.666667rem; background-image:url(images/plus.png); background-size:cover; } .choose-item .count{ font-size:0.4rem; color:#2f2f2f; width:0.666667rem; height:0.666667rem; line-height:0.666667rem; margin:0 0.053333rem; text-align:center; } .menu-inner .mask{ position: fixed; left:0; right:0; bottom:0; top:0; background-color: rgba(0,0,0,.7); }
menu.js
(function(){ //加载左侧类目 function initleftbar(){ //左侧类目的模板字符串 var itemtpl='<div class="left-item">'+ '<div class="item-text">$getitemcontent</div>'+ '</div>'; var itemhtml=""; var page=0;//当前页 var isloading=false;//当前是否处于加载中 //获取列表数据 function getlist(){ page++; isloading=true; $.get("../json/food.json",function(data){ var list=data.data.food_spu_tags || []; window.food_spu_tags=list;//把数据挂载到window对象上,方便其他模块调用 list.foreach(function(item,index){ var str=itemtpl.replace("$getitemcontent",getitemcontent(item)); var $target=$(str); //将item数据挂载到left-item上面 $target.data("itemdata",item); $(".left-bar-inner").append($target); }) $(".left-item").first().click();//默认显示第一个tab isloading=false; window.shopbar.changeshippingprice(data.data.poi_info.shipping_fee || 0);//更新价格 }) //关于图标的处理 function getitemcontent(data){ if(data.icon){ return '<img class="item-icon" src='+data.icon+'>'+data.name; }else{ return data.name; } } } getlist();//默认先请求一次 //滚动加载 window.addeventlistener("scroll",function(){ 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) return; getlist(); }else{ $(".loading").text("加载完成"); } } }); //左侧tab点击事件 $(".menu-inner").on("click",".left-item",function(e){ var $target=$(e.currenttarget); //添加点击样式 $target.addclass("active"); $target.siblings().removeclass("active"); //将数据传给右侧详情列表 initrightcontent($target.data("itemdata"));//加载右侧商品 }) } //加载右侧商品 function 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(function(item,index){ //默认为0 if(!item.choosecount){ item.choosecount=0; } var str=itemtpl .replace("$picture",item.picture) .replace("$name",item.name) .replace("$description",item.description) .replace("$praise_content",item.praise_content) .replace("$min_price",item.min_price) .replace("$unit",item.unit) .replace("$choosecount",item.choosecount); var $target=$(str); $target.data("itemdata",item);//把数据挂载在data属性上,方便以后获取 $(".right-list-inner").append($target); }); //右侧顶部title $(".right-title").text(data.name); //加号事件 $(".menu-item").on("click",".plus",function(e){ 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",function(e){ var $count=$(e.currenttarget).parent("").find(".count"); if($count.text()==0) return; $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();//购物车渲染 }) } //shopbar function 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); //渲染购物车数据 function 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(function(item){ item.spus.foreach(function(_item){ if(_item.choosecount>0){ var price=_item.choosecount*_item.min_price; var row=tpl.replace("$name",_item.name) .replace("$price",price)//总价 .replace("$choosecount",_item.choosecount); totalprice+=price; //挂载数据 var $row=$(row); $row.data("itemdata",_item); $strtop.append($row); } }) window.shopbar.changeallprice(totalprice);//更新总价 changedot();//更新红点 }) } window.shopbar.renderitems=renderitems;//将该方法暴露到全局 //更新单商品总价 function changeshippingprice(str){ $strbottom.find(".shipping-fee").text(str); } window.shopbar.changeshippingprice=changeshippingprice; //更新全商品总价 function changeallprice(str){ $strbottom.find(".total-price-span").text(str); } window.shopbar.changeallprice=changeallprice; //购物车里的加号事件 $strtop.on("click",".plus",function(e){ var $count=$(e.currenttarget).parent("").find(".count"); $count.text(parseint($count.text()||"0")+1); //更新挂载的数据 var $item=$(e.currenttarget).parents(".choose-item").first(); var itemdata=$item.data("itemdata"); itemdata.choosecount++;//更新挂载数据,在列表里也会同步更新 window.shopbar.renderitems();//购物车渲染 //找到当前右侧详情的数据,进行联动 $(".left-item.active").click(); }) //购物车里的减号事件 $strtop.on("click",".minus",function(e){ var $count=$(e.currenttarget).parent("").find(".count"); if($count.text()==0) return; $count.text(parseint($count.text()||"0")-1); //更新挂载的数据 var $item=$(e.currenttarget).parents(".choose-item").first(); var itemdata=$item.data("itemdata"); itemdata.choosecount--;//更新挂载数据,在列表里也会同步更新 window.shopbar.renderitems();//购物车渲染 //找到当前右侧详情的数据,进行联动 $(".left-item.active").click(); }) //点击显示或者隐藏购物车 $(".shop-icon").on("click",function(){ $(".mask").toggle(); $strtop.toggle(); }) //计算红点中的数量 function 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); }else{ $(".dot-num").hide(); } } } //暴露出来的方法 window.shopbar={}; function init(data){ initleftbar();//加载左侧类目 initshopbar();//加载购物车 } init(); })();
common.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:1.2rem; position: relative; color:#666; text-align:center; text-decoration: none; } .tab-bar .tab-item.active::after{ content:""; display: block; position: absolute; width:1.6rem; height:0.106667rem; bottom:0; background:#ffd161;/*美团黄*/ /*设置居中*/ left:50%; -webkit-transform:translatex(-50%); transform:translatex(-50%); } /*menu-inner*/ .menu-inner{ position: absolute; top:2.933333rem; left:0; right:0; bottom:0; display: flex; overflow:hidden; } .menu-inner .left-bar{ width:2.266667rem; background:#efefef; overflow:auto; height:100%; -webkit-overflow-scrolling:touch;/*局部滚动,尤其是移动端ios*/ } .menu-inner .left-bar-inner{ padding-bottom:2.266667rem; } .menu-inner .left-item{ font-size:0.373333rem; color:#656565; text-align:center; border-bottom:0.026667rem solid #bfbfbf; display: flex; justify-content: center; height:1.6rem; } .menu-inner .left-item.active{ background:#fff; } .menu-inner .item-text{ text-align:center; align-self:center; } .menu-inner .item-icon{ width:0.533333rem; height:0.533333rem; display: inline-block; margin-right:0.16rem; vertical-align:-0.106667rem; } .menu-inner .right-content{ flex:1; margin-left:0.266667rem; height:100%; overflow:hidden; -webkit-overflow-scrolling:touch;/*触屏滚动*/ } .menu-inner .right-title{ font-size:0.346667rem; color:#333; margin-top:0.266667rem; padding-left:0.106667rem; border-left:0.053333rem solid #ffd161; } .menu-inner .right-list{ height:100%; overflow:auto;/*可滚动*/ } .menu-inner .right-list-inner{ font-size:0.426667rem; padding-bottom:2.266667rem; } .right-list-inner .menu-item{ display: flex; padding:0.666667rem 0; border-bottom:0.026667rem solid #f0f0f0; position: relative; } .right-list-inner .img{ width:1.653333rem; height:1.653333rem; margin-right:0.266667rem; } .right-list-inner .menu-item-right{ flex:1; } .right-list-inner .item-title{ font-size:0.426667rem; color:#2f2f2f; } .right-list-inner .item-desc, .right-list-inner .item-zan{ color:#a9a9a9; font-size:0.32rem; margin-top:0.16rem; line-height:0.373333rem; padding-right:0.106667rem; } .right-list-inner .item-desc{ line-height:0.453333rem; } .right-list-inner .item-price{ margin-top:0.266667rem; color:#fe4d3d; font-size:0.48rem; } .right-list-inner .unit{ color:#a9a9a9; font-size:0.32rem; } .right-list-inner .select-content{ position: absolute; right:0.24rem; bottom:0.56rem; display: flex; } .right-list-inner .minus{ width:0.666667rem; height:0.666667rem; background-image:url(images/minus.png); background-size:cover; } .right-list-inner .count{ font-size:0.4rem; color:#2f2f2f; width:0.666667rem; height:0.666667rem; line-height:0.666667rem; margin:0 0.053333rem; text-align:center; } .right-list-inner .plus{ width:0.666667rem; height:0.666667rem; background-image:url(images/plus.png); background-size:cover; } /*shopbar*/ .shop-bar{ position: absolute; bottom:0; left:0; right:0; z-index:99; } .shop-bar .choose-content{ background:#fff; } .shop-bar .content-top{ height:0.933333rem; background-color:#f4f4f4; font-size:0.293333rem; display: flex; align-items: center; justify-content: flex-end; } .shop-bar .clear-car{ margin:0 0.133333rem 0 0.266667rem; position: relative; } .shop-bar .clear-car::after{ content:""; width:0.346667rem; height:0.346667rem; display: block; background-image:url(images/clear.jpeg); background-size:cover; position: absolute; top:-0.026667rem; left:-0.373333rem; } .shop-bar .bottom-content{ height:1.333333rem; display: flex; background:rgba(51,51,51,.9); } .shop-bar .shop-icon{ width:1.466667rem; height:1.466667rem; background-image:url(images/shop-icon.png); background-size:cover; margin-top:-0.4rem; margin-left:0.32rem; position: relative; } .shop-bar .dot-num{ position: absolute; background-color: #fb4e44; width:0.4rem; height:0.4rem; font-size:0.32rem; color:#fff; border:0.026667rem solid #fff; border-radius:50%; right:0; top:0.053333rem; text-align: center; line-height:0.4rem; } .shop-bar .price-content{ flex:1; padding-top:0.213333rem; padding-left:0.186667rem; } .shop-bar .total-price{ font-size:0.533333rem; color:#fff; } .shop-bar .total-price-span{ } .shop-bar .other-price{ font-size:0.32rem; color:#999; margin-top:0.053333rem; } .shop-bar .shipping-fee{ } .shop-bar .submit-btn{ width:2.933333rem; height:100%; background:#ffd161; color:#333; font-size:0.426667rem; line-height:1.333333rem; text-align:center; } .choose-item{ display: flex; font-size:0.4rem; color:#2f2f2f; height:0.933333rem; align-items: center; padding:0.266667rem 0; border-bottom:0.026667rem solid #ddd; } .choose-item .item-name{ flex:1; padding-left:0.266667rem; } .choose-item .price{ margin:0 0.666667rem 0 0.133333rem; } .choose-item .total{ } .choose-item .select-content{ position: relative; margin-right:0.213333rem; display: flex; } .choose-item .minus{ width:0.666667rem; height:0.666667rem; background-image:url(images/minus.png); background-size:cover; } .choose-item .plus{ width:0.666667rem; height:0.666667rem; background-image:url(images/plus.png); background-size:cover; } .choose-item .count{ font-size:0.4rem; color:#2f2f2f; width:0.666667rem; height:0.666667rem; line-height:0.666667rem; margin:0 0.053333rem; text-align:center; } .menu-inner .mask{ position: fixed; left:0; right:0; bottom:0; top:0; background-color: rgba(0,0,0,.7); }
common.js
(function(){ //加载底部菜单 function 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", text:"首页" },{ key:"order", text:"订单" },{ key:"my", text:"我的" }]; var str=""; items.foreach(function(item){ str+=itemtpl.replace(/\$key/g,item.key)//正则解决全局替换的问题 .replace("$text",item.text); }); $(".bottom-bar").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页的头部 function inittabbar(){ //menu页的模板字符串 var itemtpl='<a class="$key tab-item" href="../$key/$key.html">'+ '$text'+ '</a>'; var items=[{ key:"menu", text:"点菜" },{ key:"comment", text:"评价" },{ key:"restaurant", text:"商家" }]; var str=""; items.foreach(function(item){ str+=itemtpl.replace(/\$key/g,item.key)//正则解决全局替换的问题 .replace("$text",item.text); }); $(".tab-bar").append(str); //判断当前属于哪个页面 var arr=window.location.pathname.split("/"); var page=arr[arr.length-1].replace(".html","");//最后一个元素,去掉.html $("a."+page).addclass("active"); } function init(){ initbottombar();//加载底部菜单 inittabbar();//加载menu页的头部 } init(); })();
food.json
太多了放不上来,大家自己琢磨吧==