C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

时间:2022-02-22 23:41:44

感谢广大博问博友的帮助和共同研究讨论,终于实现了一个无缓存无刷新仿购物车的小功能:

一、实现效果简述:

有一种列表,是由双层Repeater嵌套,第一层用来显示类别,第二层用来显示类别下的商品数据,

其显示效果如下:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

且每一个菜名都可以单独点开进行配餐选择,效果如下:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

现在要在页面无刷新不计入缓存(在最后提交选餐数据的时候计入缓存,类似购物车,但这里不希望页面刷新)

的情况下将所选择的商品名称和数量无重复的添加到一个叫做“餐饮盒”的容器里:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

最终实现结果:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

在修改订购数量的时候只修改餐饮盒中该商品的总价格,商品名称不能重复,并重新计算所有商品的总价格:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

二、实现代码:

1.前台界面由2个Repeater组成:

                        <asp:Repeater ID="rptFoodKindList" runat="server" OnItemDataBound="rptFoodKindList_OnItemDataBound">
<ItemTemplate>
<div class="Cp_fl">
<%#Eval("CategoryTwoName") %><asp:HiddenField ID="hidCategoryTwoID" Value='<%#Eval("CategoryTwoID") %>'
runat="server" />
</div>
<asp:Repeater ID="rptFoodList" runat="server" OnItemDataBound="rptFoodList_OnItemDataBound">
<ItemTemplate>
<div class="CP_con">
<ul>
<li class="CP_xh"><span id="spIndex" runat="server"></span></li>
<li class="CP_name"><span id="spProName">
<%#Eval("ProductName") %></span></li>
<li class="CP_jg">¥<%#decimal.Parse(Eval("Price").ToString()).ToString("f2") %></li>
<li class="CP_fs">(已选<span id="spCount">0</span>份)<asp:HiddenField ID="hidProductID"
runat="server" Value='<%#Eval("ProductID") %>' />
</li>
</ul>
<div class="CP_mx" style="display: none;">
<div class="img">
<img src="../ProductImg/160x120/201403011616.png" />
<a href="#">点击查看大图</a>
</div>
<div class="right">
<div class="R_name">
菜名:<%#Eval("ProductName") %>
</div>
<div class="R_dj">
单价:<span id="spPrice" runat="server">¥<%#decimal.Parse(Eval("Price").ToString()).ToString("f2") %></span>
元/份</div>
<div class="R_numer">
<span>订购数量:</span><a id="aRed" class="Redu1" runat="server"></a><input id="txtBuyNum"
type="text" value="1" runat="server" /><a class="Add1" id="aAdd" runat="server"></a></div>
<div class="R_but">
<a class="Add_CD" id="aAddTo" runat="server">加到我的餐饮盒</a><a class="Redu_CD">取消</a></div>
</div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
<asp:HiddenField ID="hidProInfo" runat="server" />

2.主要Jquery代码:

(1)控制商品详情的显示和隐藏:

         $(function(){
var n = 0; //商品详情和订购选择区域默认隐藏
$(".CP_con").each(function () {
var t = $(this);//获取当前的行
t.find("ul").click(function () {
if (n == 0) {//如果隐藏则显示
t.find(".CP_mx").show();
n = 1; //设置为显示
}
else {//如果显示则隐藏
t.find(".CP_mx").hide();
n = 0;
}
}); var $cancel = $(".Redu_CD");//取消
var $CP_mx = $(".CP_mx");
t.find($cancel).click(function () {
t.find($CP_mx).hide();
});
//鼠标放置和离开时当前行的样式控制,这里是淡蓝色;
$(".CP_con>ul").mouseover(function () {
$(this).attr("style", "background-color:#F5F9FD");
}).mouseout(function () {
$(this).removeAttr("style");
});
});
});
})

(2)修改商品订购数量以及更新餐饮盒情况:

        //修改订购产品数量,type=1:添加;type=2:减少
function UpdateProductNum(btn, type, price) {
var text = $(btn).parent().find(":text"); if (type == 1) {
text.val(parseInt(text.val()) + 1);
if (parseInt(text.val()) <= 0)
text.val("1");
}
else {
text.val(parseInt(text.val()) - 1);
if (parseInt(text.val()) <= 0)
text.val("1");
}
} //添加到我的餐饮盒,修改其商品数量,商品详情变动和价格计算
function AddProductNum(btn, price, proid, index) {
var proAmount = 0;//每一种商品的总价格
var text = $(btn).parent().parent().find(":text");//查找修改数量的文本框
var count = $(".CP_fs>span")[index];//获取当前商品已选择份数控件
var proname = $(".CP_name>span")[index];//获取当前商品名称控件
var spCount = $(btn).parent().parent().parent().parent().find(count);
var spProName = $(btn).parent().parent().parent().parent().find(proname); spCount.html(text.val());//将当前份数设置为文本框中选择的份数
var curAmount = price * text.val();//计算当前总订购商品的价格 if ($("#ul" + proid).length > 0) {//如果已经存在该商品
$("#ul" + proid).attr("class", proid + "|" + text.val());//样式妙用,class用来存放商品id和订购数量,便于以下隐藏域使用
$("#ul" + proid).attr("title", "单价:¥"+price+".00;数量:"+text.val()+"份");//设置提示信息
$("#ul" + proid).html("<li class='li_l' >" + spProName.html() + "</li><li class='li_r'>¥" + curAmount + ".00</li>");//修改该商品的总价格信息
}
else {//不存在则添加一行
$("#divFoodBox").html($("#divFoodBox").html() + "<ul id='ul" + proid + "' class='" + proid + "|" + text.val() + "' title='单价:¥"+price+".00;数量:"+text.val()+"份''><li class='li_l' >" + spProName.html() + "</li><li class='li_r'>¥" + curAmount + ".00</li><ul>");
} $("#divFoodBox .li_r").each(function () {//循环查找显示总价格的li控件
proAmount += parseFloat($(this).html().replace("¥", ""));//计算当前行商品总价格并追加到临时变量中;
}); var arrClass="";//初始化样式字符串
$("#divFoodBox>ul").each(function () {
arrClass+=$(this).attr("class")+",";
}); $("#hidProInfo").val(arrClass);
$("#liSum").html("¥" + proAmount+ ".00");//更新所有订购商品总价格
}

3.后台第一个Reapeter绑定时追加前台js方法:

        /// <summary>
/// 菜谱分类列表绑定事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void rptFoodKindList_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater rptFoodList = e.Item.FindControl("rptFoodList") as Repeater;//第一个Reapeter的每行绑定时查找第二层里面的Reapeter
HiddenField hidCategoryTwoID = e.Item.FindControl("hidCategoryTwoID") as HiddenField;
rptFoodList.DataSource = HSSM_Public_DB.PblicQuery("ProductID,ProductName,Price", "Product", "CategoryTwoID = " + hidCategoryTwoID.Value);
rptFoodList.DataBind();//绑定里面的Reapeter //循环里面Reapeter的项,并给相应控件追加前台js方法
foreach (RepeaterItem item in rptFoodList.Items)
{
HtmlInputText txtBuyNum = item.FindControl("txtBuyNum") as HtmlInputText;//查找订购数量输入框
HtmlGenericControl spPrice = item.FindControl("spPrice") as HtmlGenericControl;//查找显示价格的控件
HtmlGenericControl spIndex = item.FindControl("spIndex") as HtmlGenericControl;//查找显示该商品所属分类的序号控件
string Price = spPrice.InnerText.Replace("¥", "");
spIndex.InnerText = item.ItemIndex + + ".";//设置序号 HtmlAnchor aAdd = item.FindControl("aAdd") as HtmlAnchor;//添加订购数量的控件
HtmlAnchor aRed = item.FindControl("aRed") as HtmlAnchor;//减少订购数量的控件
HtmlAnchor aAddTo = item.FindControl("aAddTo") as HtmlAnchor;//添加到我的餐饮盒的控件
HiddenField hidProductID = item.FindControl("hidProductID") as HiddenField;//存放商品id的隐藏域 aAdd.Attributes.Add("onclick", string.Format("UpdateProductNum(this,1,{0})", Price));//追加添加订购数量的js方法
aRed.Attributes.Add("onclick", string.Format("UpdateProductNum(this,2,{0})", Price));//追加减少订购数量的js方法
aAddTo.Attributes.Add("onclick", string.Format("AddProductNum(this,{0},{1},{2})", Price, hidProductID.Value, proIndex));//追加更新我的餐饮盒详情的js方法 proIndex++;//每绑定一行商品让这个全局变量值自加1,用于前台js调用find方法寻找当前商品已选择份数和商品名称时使用,
}
}
} /// <summary>
/// 产品记录索引(全局变量)
/// </summary>
public int proIndex = ;

4.最后填写好订购人信息后计入缓存:

        /// <summary>
/// 设置Cookie
/// </summary>
protected void SetFoodList()
{
string ProInfos = hidProInfo.Value.Substring(, hidProInfo.Value.Length - );//获取最后所有的商品的id和数量信息,这里需要去掉最后一个逗号
string[] arrProInfos = ProInfos.Split(',');
HttpCookie cookieFood = new HttpCookie("MyShoppingCart");//初始化一个Cookie对象 foreach (string strProInfo in arrProInfos)
{
string strProID = strProInfo.Split('|')[];//商品id
string strProCount = strProInfo.Split('|')[];//该商品订购数量 ProModel = GetProModel(strProID);
ImagesModel = GetProImageModel(strProID); //DateTime dt = DateTime.Now;
//TimeSpan ts = new TimeSpan(0, 0, 1, 0, 0);//过期时间为1分钟
//cookie.Expires = dt.Add(ts);//设置过期时间 //设置cookie的值
cookieFood.Values.Add("Company", ComModel.Company);
cookieFood.Values.Add("ProductID", strProID);
cookieFood.Values.Add("ProductName", ProModel.ProductName);
cookieFood.Values.Add("SaleUserID", SaleUserID.ToString());
cookieFood.Values.Add("ProductImg", ImagesModel.ImageUrl);
cookieFood.Values.Add("Price", ProModel.Price.Value.ToString("f2"));
cookieFood.Values.Add("Bonus", "");
cookieFood.Values.Add("Count", strProCount); Response.Cookies.Add(cookieFood);
}
} /// <summary>
/// 保存配送信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnDispatch_Click(object sender, EventArgs e)
{
SetFoodList();
Response.Redirect("OrderInfo.aspx");
}

小插曲→计入到关键隐藏域hidProInfo的值是这样的:

C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

ok,感谢主,这个功能就此结束了,之前有博问博友建议加到餐饮盒时就加入缓存,但是考虑到需要后台处理,页面会刷新,如果用ajax也可以实现局部异步刷新,过后我再尝试一下看看,不过我这种实现方法是另一种思路,我选择最后点击“OK,下一步”的时候计入缓存到那边选餐订单确认页面获取缓存显示商品情况。其实这当中关键点就是一个class的妙用(本来class是用来指定样式表,这里用来存放数据未尝不可)和隐藏域的使用。