我从来没有进行过正式的web开发,但是我一直喜欢web,所以这篇文章也是我转行web的一个开始吧。或多或少我也参考了几个网站的实现(当然了,只是看看大概的功能而已),所以也请大家多多指教。该购物车的功能如下:
1. 通过ajax实现添加和删除车上的物品。
2. 删除的物品会显示出来,可以重新添加到购物车。
3. 嗯...没有了,具体大家接着看吧。
购物车的结构我打算用一个table来展示,在UserControl里使用ListView展现购物车的物品(因为比拼接字符串要容易维护的多)。具体代码如下(ShopCartTest.ascx):


1
<
asp:ListView
ID
="ListView1"
runat
="server"
>
2 < LayoutTemplate >
3 < table runat ="server" cellpadding ='0' cellspacing ='0' width ='100%' >
4 < tr >
5 < td width ='7%' style ='height: 30px' >
6 商品编号
7 td>
8 <td>
9 商品名称
10 td>
11 <td width='10%'>
12 京东价
13 td>
14 <td width='8%'>
15 返现
16 td>
17 <td width='8%'>
18 赠送积分
19 td>
20 <td width='9%'>
21 商品数量
22 td>
23 <td width='7%'>
24 删除商品
25 td>
26 tr>
27 <tr runat="server" id="itemPlaceholder" />
28 <tr>
29 <td colspan='7' style='height: 30px'>
30 重量总计:<%= this.GetProductsWeight() %>kg 原始金额:¥307.00元 - 返现:¥0.00元<br />
31 <span style='font-size: 14px'><b>商品总金额(不含运费):<span id='cartBottom_price'>¥307.00span>元b>span>
32 td>
33 tr>
34 table>
35 LayoutTemplate>
36 <ItemTemplate>
37 <tr>
38 <td style='padding: 5px 0 5px 0;'>
39 <%#(Container.DataItem as Product).ID %>
40 td>
41 <td>
42 <a target='_blank' href='http://www.xxx.com/product/<%#(Container.DataItem as Product).ID %>.html'>
43 <%#(Container.DataItem as Product).Name %>a>
44 td>
45 <td>
46 <span>
47 <%#(Container.DataItem as Product).Price %>span>
48 td>
49 <td>
50 <%#(Container.DataItem as Product).BackMoney %>
51 td>
52 <td>
53 <%#(Container.DataItem as Product).Score %>
54 td>
55 <td>
56 <a href='#none' title='减一' onclick="changeCount('-','<%#(Container.DataItem as Product).ID %>','sku');"
57 style='text-decoration: none'>-a><input type='text' id='txt<%#(Container.DataItem as Product).ID %>'
58 name='txtChange<%#(Container.DataItem as Product).ID %>' maxlength='4' style='width: 30px'
59 value='<%#(Container.DataItem as Product).Count %>' /><a href='#none' title='加一'
60 onclick="changeCount('+','<%#(Container.DataItem as Product).ID %>');" style='text-decoration: none'>+a>
61 td>
62 <td>
63 <a href='#none' id='btn_del_173259' onclick="removeProductOnShoppingCart('<%#(Container.DataItem as Product).ID %>',this)">
64 删除a>
65 td>
66 tr>
67 ItemTemplate>
68 asp:ListView>
2 < LayoutTemplate >
3 < table runat ="server" cellpadding ='0' cellspacing ='0' width ='100%' >
4 < tr >
5 < td width ='7%' style ='height: 30px' >
6 商品编号
7 td>
8 <td>
9 商品名称
10 td>
11 <td width='10%'>
12 京东价
13 td>
14 <td width='8%'>
15 返现
16 td>
17 <td width='8%'>
18 赠送积分
19 td>
20 <td width='9%'>
21 商品数量
22 td>
23 <td width='7%'>
24 删除商品
25 td>
26 tr>
27 <tr runat="server" id="itemPlaceholder" />
28 <tr>
29 <td colspan='7' style='height: 30px'>
30 重量总计:<%= this.GetProductsWeight() %>kg 原始金额:¥307.00元 - 返现:¥0.00元<br />
31 <span style='font-size: 14px'><b>商品总金额(不含运费):<span id='cartBottom_price'>¥307.00span>元b>span>
32 td>
33 tr>
34 table>
35 LayoutTemplate>
36 <ItemTemplate>
37 <tr>
38 <td style='padding: 5px 0 5px 0;'>
39 <%#(Container.DataItem as Product).ID %>
40 td>
41 <td>
42 <a target='_blank' href='http://www.xxx.com/product/<%#(Container.DataItem as Product).ID %>.html'>
43 <%#(Container.DataItem as Product).Name %>a>
44 td>
45 <td>
46 <span>
47 <%#(Container.DataItem as Product).Price %>span>
48 td>
49 <td>
50 <%#(Container.DataItem as Product).BackMoney %>
51 td>
52 <td>
53 <%#(Container.DataItem as Product).Score %>
54 td>
55 <td>
56 <a href='#none' title='减一' onclick="changeCount('-','<%#(Container.DataItem as Product).ID %>','sku');"
57 style='text-decoration: none'>-a><input type='text' id='txt<%#(Container.DataItem as Product).ID %>'
58 name='txtChange<%#(Container.DataItem as Product).ID %>' maxlength='4' style='width: 30px'
59 value='<%#(Container.DataItem as Product).Count %>' /><a href='#none' title='加一'
60 onclick="changeCount('+','<%#(Container.DataItem as Product).ID %>');" style='text-decoration: none'>+a>
61 td>
62 <td>
63 <a href='#none' id='btn_del_173259' onclick="removeProductOnShoppingCart('<%#(Container.DataItem as Product).ID %>',this)">
64 删除a>
65 td>
66 tr>
67 ItemTemplate>
68 asp:ListView>
我想大家应不用我解释代码的意思了,很简单。
后台代码如下:


public
partial
class
ShopCartTest : System.Web.UI.UserControl
{
List < Product > productsList = null ;
protected override void OnPreRender(EventArgs e)
{
base .OnPreRender(e);
switch (Acion)
{
case " removeProductOnShoppingCart " :
productsList = Product.GetProductsInCart(ProductID);
break ;
case " changeProductCount " :
productsList = Product.GetProductsInCart( null );
foreach (var item in productsList)
{
if (item.ID == ProductID)
{
item.Count = " 3 " ;
}
}
break ;
case " AddProduct " :
productsList = Product.GetProductsInCart( null );
productsList.Add( new Product() { ID = " 173233 " , Name = " ElandMX9470 " , Price = " 399.00 " , BackMoney = " 0.00 " , Score = " 0 " , Count = " 1 " });
break ;
default :
productsList = Product.GetProductsInCart(ProductID);
break ;
}
ListView1.DataSource = productsList;
ListView1.DataBind();
}
public string GetProductsWeight()
{
return Product.GetProductsInCart(ProductID).Sum(p => decimal .Parse(p.Price) * decimal .Parse(p.Count)).ToString();
}
public string GetProductsOriginalPrice()
{
return Product.GetProductsInCart(ProductID).Sum(p => decimal .Parse(p.Price) * decimal .Parse(p.Count)).ToString();
}
public string ProductID { get ; set ; }
public string Acion { get ; set ; }
}
{
List < Product > productsList = null ;
protected override void OnPreRender(EventArgs e)
{
base .OnPreRender(e);
switch (Acion)
{
case " removeProductOnShoppingCart " :
productsList = Product.GetProductsInCart(ProductID);
break ;
case " changeProductCount " :
productsList = Product.GetProductsInCart( null );
foreach (var item in productsList)
{
if (item.ID == ProductID)
{
item.Count = " 3 " ;
}
}
break ;
case " AddProduct " :
productsList = Product.GetProductsInCart( null );
productsList.Add( new Product() { ID = " 173233 " , Name = " ElandMX9470 " , Price = " 399.00 " , BackMoney = " 0.00 " , Score = " 0 " , Count = " 1 " });
break ;
default :
productsList = Product.GetProductsInCart(ProductID);
break ;
}
ListView1.DataSource = productsList;
ListView1.DataBind();
}
public string GetProductsWeight()
{
return Product.GetProductsInCart(ProductID).Sum(p => decimal .Parse(p.Price) * decimal .Parse(p.Count)).ToString();
}
public string GetProductsOriginalPrice()
{
return Product.GetProductsInCart(ProductID).Sum(p => decimal .Parse(p.Price) * decimal .Parse(p.Count)).ToString();
}
public string ProductID { get ; set ; }
public string Acion { get ; set ; }
}
把对购物车的逻辑都写到这里面,通过action来判断是什么操作,一样简单的代码。再来看看Product类:


public
class
Product
{
public string ID { get ; set ; }
public string Name { get ; set ; }
public string Price { get ; set ; }
public string BackMoney { get ; set ; }
public string Score { get ; set ; }
public string Count { get ; set ; }
public static List < Product > GetProductsInCart( string productID)
{
List < Product > list = new List < Product > ()
{
new Product{ID = " 173259 " ,Name = " 毛毛仔妮妮熊MX9470 " ,Price = " 99.00 " ,BackMoney = " 0.00 " ,Score = " 0 " ,Count = " 1 " },
new Product{ID = " 155097 " ,Name = " xxxxxx新款轻巧便携式电脑桌(送鼠标垫) " ,Price = " 79.00 " ,BackMoney = " ¥0.00 " ,Score = " 0 " ,Count = " 1 " },
new Product{ID = " 155098 " ,Name = " xxxxxx护眼台灯(理想)STL-T412W-03WT " ,Price = " 69.00 " ,BackMoney = " ¥0.00 " ,Score = " 0 " ,Count = " 1 " }
};
return list.Where(p => { return p.ID != productID; }).ToList();
}
}
{
public string ID { get ; set ; }
public string Name { get ; set ; }
public string Price { get ; set ; }
public string BackMoney { get ; set ; }
public string Score { get ; set ; }
public string Count { get ; set ; }
public static List < Product > GetProductsInCart( string productID)
{
List < Product > list = new List < Product > ()
{
new Product{ID = " 173259 " ,Name = " 毛毛仔妮妮熊MX9470 " ,Price = " 99.00 " ,BackMoney = " 0.00 " ,Score = " 0 " ,Count = " 1 " },
new Product{ID = " 155097 " ,Name = " xxxxxx新款轻巧便携式电脑桌(送鼠标垫) " ,Price = " 79.00 " ,BackMoney = " ¥0.00 " ,Score = " 0 " ,Count = " 1 " },
new Product{ID = " 155098 " ,Name = " xxxxxx护眼台灯(理想)STL-T412W-03WT " ,Price = " 69.00 " ,BackMoney = " ¥0.00 " ,Score = " 0 " ,Count = " 1 " }
};
return list.Where(p => { return p.ID != productID; }).ToList();
}
}
接下来在ShopCartDetail.aspx页面使用该UserControl:
<
div
id
="products"
>
< demo:ShopCartTest ID ="ShopCartTest1" runat ="server" />
div>
< demo:ShopCartTest ID ="ShopCartTest1" runat ="server" />
div>
通过ajax使用购物车还需要两个类:


public
class
GetProducts : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = " text/plain " ;
ViewManager < ShopCartTest > viewManager = new ViewManager < ShopCartTest > ();
ShopCartTest control = viewManager.LoadViewControl( " ~/ShopCartTest.ascx " );
control.ProductID = context.Request.QueryString[ " productId " ];
control.Acion = context.Request.QueryString[ " action " ];
context.Response.Write(viewManager.RenderView(control));
}
public bool IsReusable
{
get
{
return false ;
}
}
}
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = " text/plain " ;
ViewManager < ShopCartTest > viewManager = new ViewManager < ShopCartTest > ();
ShopCartTest control = viewManager.LoadViewControl( " ~/ShopCartTest.ascx " );
control.ProductID = context.Request.QueryString[ " productId " ];
control.Acion = context.Request.QueryString[ " action " ];
context.Response.Write(viewManager.RenderView(control));
}
public bool IsReusable
{
get
{
return false ;
}
}
}


public
class
ViewManager
<
T
>
where
T : UserControl
{
private Page m_pageHolder;
public T LoadViewControl( string path)
{
m_pageHolder = new Page();
return this .m_pageHolder.LoadControl(path) as T;
}
public string RenderView(T control)
{
StringWriter output = new StringWriter();
this .m_pageHolder.Controls.Add(control);
HttpContext.Current.Server.Execute( this .m_pageHolder, output, false );
return output.ToString();
}
}
{
private Page m_pageHolder;
public T LoadViewControl( string path)
{
m_pageHolder = new Page();
return this .m_pageHolder.LoadControl(path) as T;
}
public string RenderView(T control)
{
StringWriter output = new StringWriter();
this .m_pageHolder.Controls.Add(control);
HttpContext.Current.Server.Execute( this .m_pageHolder, output, false );
return output.ToString();
}
}
这两个类是参考老赵提出来的方案完成,具体原理,你可以看这里。
剩下来都是javascript了,这里我并没有使用任何类库或者框架。代码如下:


1
function
ajaxCommon(requst) {
2 var xmlHttp = false ;
3 if (window.ActiveXObject) {
4 xmlHttp = new ActiveXObject( " Microsoft.XMLHTTP " );
5 }
6 else {
7 if (window.XMLHttpRequest) {
8 xmlHttp = new XMLHttpRequest();
9 }
10 }
11 xmlHttp.onreadystatechange = function () { getAjaxValue(xmlHttp) }
12 xmlHttp.open( " GET " , " /GetProducts.ashx " + ' ?roid= ' + Math.random() + ' & ' + requst);
13 xmlHttp.send( null );
14 }
15
16 function getAjaxValue(xmlHttp) {
17
18 if (xmlHttp.readyState == 4 ) {
19 if (xmlHttp.status == 200 ) {
20 document.getElementById( " products " ).innerHTML = xmlHttp.responseText;
21 }
22 }
23 }
24
25 function addProduct(productID, productCount) {
26 ajaxCommon( " action=AddProduct&productId= " + productID + " &productCount= " + productCount);
27 }
28
29 function removeProductOnShoppingCart(productId, obj) {
30 debugger ;
31 setDelProduct(obj, productId);
32
33 ajaxCommon( " action=removeProductOnShoppingCart&productId= " + productId);
34
35 setDelProductShow();
36 }
37
38 function changeCount(type, productID) {
39 var changeCount = 0 ;
40 var txtCount = 0 ;
41 if (type == " - " ) {
42 changeCount = - 1 ;
43 }
44 if (type == " + " ) {
45 changeCount = 1 ;
46 }
47 txtCount = document.getElementById( " txt " + productID).value;
48
49 ajaxCommon( " action=changeProductCount&productId= " + productID + " &productCount= " + txtCount);
50 }
51
52 function DeledProductInfo() {
53 this .ID = '' ;
54 this .Name = '' ;
55 this .Price = '' ;
56 this .Count = '' ;
57 }
58
59 var delProduct = null ;
60 function setDelProduct(obj, productID) {
61 try {
62 delProduct = new DeledProductInfo();
63 var trObj = obj.parentNode.parentNode;
64
65 delProduct.ID = trObj.cells[ 0 ].innerHTML;
66 delProduct.Name = trObj.cells[ 1 ].innerHTML;
67 delProduct.Price = trObj.cells[ 2 ].innerHTML;
68 delProduct.Count = document.getElementById( ' txt ' + productID).value;
69 } catch (e) { }
70
71 }
72
73 function setDelProductShow() {
74 try {
75 if (document.getElementById( ' divDeledProduct ' ) == null ) return ;
76 if (delProduct != null && delProduct.ID != '' ) {
77 var dHtml = " <table><tr> " ;
84 dHtml += "<td style='width:70px'>" + delProduct.ID + "</td>";
79 dHtml += "<td style='text-align:left'>" + delProduct.Name + "</td>";
80 dHtml += "<td>" + delProduct.Price + "</td>";
81 dHtml += "<td>" + delProduct.Count + "</td>";
82 dHtml += "<td><a href='#none' οnclick=\"addProduct('" + delProduct.ID + "','" + delProduct.Count + "');reAddedProduct('delProduct" + delProduct.ID + "');\">重新购买</a></td>";
83 dHtml += "</tr></table>";
85 document.getElementById( ' divDeledProduct ' ).style.display = '' ;
86
87 document.getElementById( ' divDeledProduct ' ).innerHTML += "
88
89 }
90
91 delProduct = null ;
92 } catch (e) { }
93 }
94
95 function reAddedProduct(reAddDivId) {
96 try {
97 debugger ;
98 document.getElementById( ' divDeledProduct ' ).removeChild(document.getElementById(reAddDivId));
99 if (document.getElementById( ' divDeledProduct ' ).childNodes.length == 0 ) {
100 document.getElementById( ' divDeledProduct ' ).style.display = ' none ' ;
101 }
102 } catch (e) { }
103 }
2 var xmlHttp = false ;
3 if (window.ActiveXObject) {
4 xmlHttp = new ActiveXObject( " Microsoft.XMLHTTP " );
5 }
6 else {
7 if (window.XMLHttpRequest) {
8 xmlHttp = new XMLHttpRequest();
9 }
10 }
11 xmlHttp.onreadystatechange = function () { getAjaxValue(xmlHttp) }
12 xmlHttp.open( " GET " , " /GetProducts.ashx " + ' ?roid= ' + Math.random() + ' & ' + requst);
13 xmlHttp.send( null );
14 }
15
16 function getAjaxValue(xmlHttp) {
17
18 if (xmlHttp.readyState == 4 ) {
19 if (xmlHttp.status == 200 ) {
20 document.getElementById( " products " ).innerHTML = xmlHttp.responseText;
21 }
22 }
23 }
24
25 function addProduct(productID, productCount) {
26 ajaxCommon( " action=AddProduct&productId= " + productID + " &productCount= " + productCount);
27 }
28
29 function removeProductOnShoppingCart(productId, obj) {
30 debugger ;
31 setDelProduct(obj, productId);
32
33 ajaxCommon( " action=removeProductOnShoppingCart&productId= " + productId);
34
35 setDelProductShow();
36 }
37
38 function changeCount(type, productID) {
39 var changeCount = 0 ;
40 var txtCount = 0 ;
41 if (type == " - " ) {
42 changeCount = - 1 ;
43 }
44 if (type == " + " ) {
45 changeCount = 1 ;
46 }
47 txtCount = document.getElementById( " txt " + productID).value;
48
49 ajaxCommon( " action=changeProductCount&productId= " + productID + " &productCount= " + txtCount);
50 }
51
52 function DeledProductInfo() {
53 this .ID = '' ;
54 this .Name = '' ;
55 this .Price = '' ;
56 this .Count = '' ;
57 }
58
59 var delProduct = null ;
60 function setDelProduct(obj, productID) {
61 try {
62 delProduct = new DeledProductInfo();
63 var trObj = obj.parentNode.parentNode;
64
65 delProduct.ID = trObj.cells[ 0 ].innerHTML;
66 delProduct.Name = trObj.cells[ 1 ].innerHTML;
67 delProduct.Price = trObj.cells[ 2 ].innerHTML;
68 delProduct.Count = document.getElementById( ' txt ' + productID).value;
69 } catch (e) { }
70
71 }
72
73 function setDelProductShow() {
74 try {
75 if (document.getElementById( ' divDeledProduct ' ) == null ) return ;
76 if (delProduct != null && delProduct.ID != '' ) {
77 var dHtml = " <table><tr> " ;
84 dHtml += "<td style='width:70px'>" + delProduct.ID + "</td>";
79 dHtml += "<td style='text-align:left'>" + delProduct.Name + "</td>";
80 dHtml += "<td>" + delProduct.Price + "</td>";
81 dHtml += "<td>" + delProduct.Count + "</td>";
82 dHtml += "<td><a href='#none' οnclick=\"addProduct('" + delProduct.ID + "','" + delProduct.Count + "');reAddedProduct('delProduct" + delProduct.ID + "');\">重新购买</a></td>";
83 dHtml += "</tr></table>";
85 document.getElementById( ' divDeledProduct ' ).style.display = '' ;
86
87 document.getElementById( ' divDeledProduct ' ).innerHTML += "
"
+
dHtml
+
"
"
;88
89 }
90
91 delProduct = null ;
92 } catch (e) { }
93 }
94
95 function reAddedProduct(reAddDivId) {
96 try {
97 debugger ;
98 document.getElementById( ' divDeledProduct ' ).removeChild(document.getElementById(reAddDivId));
99 if (document.getElementById( ' divDeledProduct ' ).childNodes.length == 0 ) {
100 document.getElementById( ' divDeledProduct ' ).style.display = ' none ' ;
101 }
102 } catch (e) { }
103 }
代码依旧很容易看懂,需要解释的就是删除的操作,分为三步:
- 将需要删除的物品先保存起来:setDelProduct(obj, productId);
- 在后台购物车清单上面将物品删除,并返回删除后的物品清单:ajaxCommon("action=removeProductOnShoppingCart&productId=" + productId);
- 将删除的物品输出,放到已删除列表(完全在客户端操作):setDelProductShow();
还有从删除列表中将删除的物品重新添加到购物车当中,分为两步:
- 在后台将物品添加到物品清单(和直接添加物品调用同一个方法):addProduct
- 从已删除列表中将该物品删除(完全在客户端操作):reAddedProduct
这样,一个基本的购物车就完成了。但是具体对于数据的操作,需要您进一步处理。本文对于数据的操作只是示例而已。