zoukankan      html  css  js  c++  java
  • 《纯JS写的无刷新实时同步购物车系统》

    《纯JS写的无刷新实时同步购物车系统》

    前言

    开发一个电子商务网站要考虑的最基本的四个模块分别是产品模块、购物车模块、订单模块以及个人中心模块,除了个人中心模块其他的三个模块都是必要的(最起码的浏览商品加入购物车下单)。产品模块在我的第一篇博文关注电子商务网站开发-《产品表结构》已经提到,今天要写的是购物车模块,JS面向对象+Jquery,支持绝大部分电子商务网站,希望可以给一些准备做这一行或者对这行感兴趣的同学一些启发。

    文章主要说明思路并解释重要部分的代码,结尾会附上源码。

    引用

    主要用到的插件$.cookie这个插件在我上一篇文章中已经介绍关注电子商务网站开发-《简单易用的JQUERY插件--图片延时加载插件(lazyload)》

    思路

    第一步:声明购物车对象

    代码

    复制代码
    Cart = {
        Product: new Array(),
        TotalPrice: 0,
        Limit: 40,
        Add: function (product) {
            //...
        },
        FindProductBySku: function (sku){
            //...
        },
        Account: function () {
            //...
        },
        SaveCookie: function () {
            //...
        },
        ClearCookie: function () {
            //...
        },
        Load: function () {
            //...
        }
    }
    复制代码

    购物车中有众多属性和方法,如产品集合Product;总价格TotalPrice;个数限制Limit;添加一个商品到购物车Add;查找购物车中是否存在某商品FindProductBySku;计算价格Account;保存产品信息到cookie中的SaveCookie;清除购物车的ClearCookie;加载购物车的Load。还有一些其他方法,就不一一介绍了,感兴趣的可以在源码中查看。

    第二步:加入购物车

    加入购物车是通过方法Add操作的,参数为product对象,product对象也有自己的属性,有名称name,编码sku,价格price,添加的个数count,属性attribute,添加的时候要先声明一个product对象,并且为product的每个属性赋值,代码如:

    复制代码
    var product = {};
    var para=’201210120006,商品X,480,1,红色’;
                    product.sku = para.split(',')[0];
                    product.name = para.split(',')[1];
                    product.price = para.split(',')[2];
                    product.count = para.split(',')[3];
                    product.attribute = para.split(',')[4];
                    Cart.Add(product);
    复制代码

    添加商品的主要思路是判断购物车是否有商品,如果没有,显示购物车并且添加商品;如果有,判断购物车中是否存在该商品(用到方法:FindProductBySku),如果存在,则数量增加,如果不存在,则添加到购物车。

    第三步:计算价格和个数

    总价格的计算是通过遍历产品集合然后相加得到的,总个数也就是产品集合的个数,相对来说这一步比较简单。

    代码:

    复制代码
    Account: function () {
            var allamount = 0.0;
            for (var i = 0; i < this.Product.length; i++) {
                var price = this.Product[i].price; //单价
                var count = this.Product[i].count; //单价
                var rowamount = parseFloat(price) * parseFloat(count); //单个总价
                allamount += rowamount;
            }
            this.TotalPrice = parseFloat(allamount).toFixed(1);
            
        }
    复制代码


     

    第四步:保存到cookie

    为了保证购物车是全局的,产品信息必须要记录到cookie中,期限为3天,原则是每种产品记录一条,这是考虑到浏览器cookie的大小限制,还要考虑到cookie的个数限制,所以加入购物车时也会做一个个数限制。每条cookie记录了产品的所有属性,每种属性用符号^隔开,用符号隔开是为了加载的时候解析,用^符号是因为有些产品的名字也可能出现一些常用的标点符号。同时为了全局实时的显示购物车的数量,可以在网站通用的头部加个ID为cartcount元素,这样每一次添加商品都会做相应的显示。

    代码:

    复制代码
    SaveCookie: function () {
            for (var i = 0; i < this.Product.length; i++) {
                var productSku = this.Product[i].sku; //产品编码
                var productName = this.Product[i].name; //产品名称
                var productPrice = this.Product[i].price; //产品单价
                var productCount = this.Product[i].count; //产品数量
                var productAttribute = this.Product[i].attribute; //产品属性
                var productInfo = productSku + "^" + productName + "^" + productPrice + "^" + productCount + "^" + productAttribute
                $.cookie("productInfo" + i, productInfo, { expires: 3, path: '/' });
            }
            $.cookie("cartCount", this.Product.length, { expires: 3, path: '/' });
            $.cookie("cartTotlePrice", this.TotalPrice, { expires: 3, path: '/' });
            $("#cartcount").html(this.Product.length);
    }
    复制代码

    其他:

    还有一个LOAD方法,此方法是在进入购物车页面或者进入要进行购物车操作页面(商品列表页面)时调用的,代码:

    复制代码
    Load: function () {
            var cartCount = $.cookie("cartCount") - 0;
            if (cartCount != 0) {
                for (var i = 0; i < cartCount; i++) {
                    var productInfo = $.cookie("productInfo" + i);
                    var product = {};
                    var temp = "";
                    var productItemPrice = "";
    
                    product.sku = productInfo.split('^')[0]; //产品编码
                    product.name = productInfo.split('^')[1]; //产品名称
                    product.price = productInfo.split('^')[2]; //产品单价
                    product.count = productInfo.split('^')[3]; //产品数量
                    product.attribute = productInfo.split('^')[4]; //产品属性
                    this.Product.push(product);
                }
                Cart.Account();
            }
           
        }
    复制代码

    基本方法就这些,这里做了两个页面用来实现购物车功能,感兴趣的同学可以去体验一下。

    点击这里:购物车页面商品列表页面

    点击这里下载

    .NET集合总结

     

            集合是一些有共同特征的独立数据项组成的,通过集合,我们可以可以使用相同的调用代码来处理一个集合的所有元素,而不用单独处理每一个单独的项。.net的集合诸如(System.Array类以及 System.Collections命名空间)数组、列表、队列、堆栈、哈希表、字典甚至(System.Data下)DataSet、DataTable,还有2.0中加入的集合的泛型版本(System.Collections.Generic和 System.Collections.ObjectModel),4.0中引入的有效线程安全操作的集合(System.Collections.Concurrent)。

            面对这么多的集合,你了解各个集合有哪些优势,在一个特定的场景中使用哪个集合吗?本文试图探讨一下这个问题,泛泛而谈,不涉及深入的内存数据结构的追究,希望能给大家带来一些益处。

    集合接口

            在分别讨论各种集合之前,我们先讨论一下集合的共性,整个集合体系的继承层次。

            ICollection 接口是 System.Collections 命名空间中类的基接口,而相应的ICollection<T>是所有泛型版本集合的基接口。所有的的集合类都直接或间接的继承他们。

            ICollection又继承IEnumerable,来提供方便的枚举功能,不过更值得注意ICollection提供同步访问的线程安全性控制:

            IsSynchronized:获取一个值,该值指示是否同步对 ICollection 的访问(线程安全)。


            SyncRoot:获取可用于同步对 ICollection 的访问的对象。

            例如,我们可以通过以下来对集合进行线程安全访问,不过有些集合提供Synchronized方法来提供线程安全集合的封装。

    ICollection myCollection = someCollection;
    lock(myCollection.SyncRoot)
    {
           // Insert your code here.
    }

           不过默认情况下集合不是线程安全的。如果需要对集合进行可伸缩的且高效的多线程访问,请使用System.Collections.Concurrent命名空间中的某个类。       

           而与非泛型版本不同的是,泛型版本的集合除了实现了泛型的接口外,也实现了非泛型的相应的接口。如ICollection<T>实现了IEnumerable和IEnumerable<T>,但是泛型集合却没有提供同步访问的线程安全控制,也就是说泛型集合的同步访问,我们必须自己去处理同步或使用System.Collections.Concurrent命名空间中的某个类。

            另外,IList和IDictionary分别继承自ICollection,IList的实现者(如Array、ArrayList 或 List<T>等)和ICollection的实现者(例如 Queue、ConcurrentQueue<T>、Stack、 ConcurrentStack<T>或 LinkedList<T>)的每个元素都是一个值,而IDictionary的实现者(例如 Hashtable 和 SortedList 类、Dictionary<TKey, TValue> 和 SortedList<TKey, TValue> 泛型类)每个元素都是一个键值对。

            接下来,我们将分别讨论和比较下一些常用的集合。

    数组Array

            Array不是System.Collections的一部分,但是它继承自IList接口。.net的Array可以有多维数组、交错数组,甚至创建下限不是0是数组,默认情况下推荐使用下限是0的一维数组,这常用的数组是经过优化的,性能最高。

            与System.Collections集合不同的是,Array具有固定的容量,若要增加容量,您必须创建具有所需容量的新 Array 对象,将旧 Array 对象中的元素复制到新对象中,然后删除该旧 Array。而System.Collections下的集合在达到当前容量时可自动扩充容量:内存被重新分配,元素从旧集合复制到新集合中。 这减少了使用集合所需的代码,但是,集合的性能可能仍受到消极影响。 因此我们应将初始容量设置为集合的估计的大小以避免因多次重新分配导致的不佳性能。

    System.Collections下的集合类

            该类型的集合都具有排序功能且大多数经过了索引。能自动处理内存管理,容量按需扩大。

            ArrayList和List<T>:List<T>是ArrayList的泛型版本,它们和Array一样都是基于索引访问,每个数据项只保存一个数据值,但是它们提供比Array更强大的功能和操作,使得它们也更容易使用。性能方面,泛型版本总是比非泛型更优先采用,除非成员类型是object类型,因为泛型版本免除了装箱和拆箱的操作;在不需要重新分配集合容量的情况下,List<T>的性能与同类型的数组十分相近。另外,ArrayList可以很方便的创建同步版本,但Array和List<T>的同步工作必须有自己完成。

            Hashtable 和 Dictionary 集合类型:这些集合每个项是一个键值对。Dictionary<Tkey,Tvalue>是Hashtable的泛型版本。Hashtable对象是由包含集合元素的存储桶组成的,每个存储桶与使用元素键基于哈希函数生成的一个哈希码关联,包含多个元素。因此这类集合比其它的大多数集合在搜索和检索数据上更快捷。而同样的Dictionary<Tkey,Tvalue>总是比Hashtable性能更好,因此推荐使用,多线程同步使用ConcurrentDictionary<TKey, TValue>类。

            已排序的集合类型:System.Collections.SortedList 类、System.Collections.Generic.SortedList<TKey, TValue> 泛型类和System.Collections.Generic.SortedDictionary<TKey, TValue> 泛型类,它们都实现 IDictionary 接口,两个泛型类还实现了System.Collections.Generic.IDictionary<TKey, TValue>,与Hashtable类似每个元素都是一个键值对,但是它们以基于键的排序顺序维护元素,并没有哈希表的 O(1) 插入和检索特性。非泛型的枚举项是DictionaryEntry 对象,而两个泛型类型返回 KeyValuePair<TKey, TValue> 对象。它们最重要的重点是它们是按照System.Collections.IComparer实现或System.Collections.Generic.IComparer<T>的实现排好序的。SortedList允许我们通过索引和键访问,而SortedDictionary只能通过键访问,SortedList还更省内存。

            队列和堆栈:就不多做介绍了,如果要临时存储数据,数据只在访问一次后就放弃,就可以使用这类集合。队列和堆栈的差别就在于访问的先后不一样,相信大家都很清楚了。他们也分别有各自的泛型版本和线程安全版本:System.Collections.Queue 类、System.Collections.Generic.Queue<T> 类和System.Collections.Concurrent.ConcurrentQueue<T>,System.Collections.Stack类以及 System.Collections.Generic.Stack<T> 和System.Collections.Concurrent.ConcurrentStack<T>。

            Set集合:该类型集合的两个类型HashSet<T> 和 SortedSet<T>,都实现了ISet<T>接口。Set集合最接近于数学中的集合,专门用于实现了数学的Set操作,如并集、交集等运算。其中Hashset<T>没有排序,不能有重复元素,可以视为Dictionary<TKey,TValue>的不包含值的版本,基于哈希键提供高性能的Set运算。而SortedSet<T>提供排好序的Set操作的集合。这里要提的是有些集合也提供了Set运算的扩展方法和LINQ也提供的Set运算,不过它们都返回新 的IEnumerable<T>集合,而Set集合的Set操作都是修改当前集合,并且提供一个更大、更可靠的运算集合。

    这并不是.net集合的全部,它还有位集合和专用集合。    

    位集合

            它的每个元素是一个标识位,而不是对象。其中有BitVector32和BitArray。

            BitVector32是一个结构,只能存储32位数据,可用来存储位标识或小整数,它是值类型,因此性能更好。

            而BitArray是引用类型,它的容量始终与计数相同,可以通过Length属性来分配或删除元素。

    专用集合

            NameValueCollection 基于 NameObjectCollectionBase;但NameValueCollection 接受一键多值,而 NameObjectCollectionBase 只接受一键一值。

            System.Collections.Specialized 命名空间中的一些强类型集合包括 StringCollection 和 StringDictionary,它们都包含完全是字符串的值集合和字典。

            CollectionsUtil 类提供一系列静态方法可以用来创建不区分大小写的Hashtable或SortedList集合的实例。

            有些集合可以转换。例如,HybridDictionary 类起初是 ListDictionary,增大后就变为 Hashtable。

            另外,KeyedCollection<TKey, TItem> 是介于列表和字典之间的混合类型,它提供了一种存储包含自己键的对象的方法,当元素数目达到指定阈值时,它也可以创建查找字典。

            ListDictionary:使用单向链接列表实现 IDictionary。建议为通常包括少于 10 个项目的集合,当数据项较少时,提供比Hashtable更好的性能。

    LINQ to Objects

             我们可以使用 LINQ 查询来访问内存中的实现了System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable<T> 接口对象。

            它提供了一种通用的数据访问模式;与标准 foreach 循环相比,它通常更加简洁,可读性更高;提供了强大的筛选、排序和分组功能。

    如何抉择

            我们首先要明确,如果存在泛型版本,优先使用。

            选择之前请先确定几个问题:

            是否需要按序列访问,元素在访问后放弃?

            访问的顺序是先进先出或后进先出、随机访问?

            是基于索引的访问,还是基于键的访问?

            是只有值,还是键值对形式?

            是一对一,还是一对多?

            是否允许重复?

            是按进入的顺序保存,还是需要按一定的规则排好序的,还是无所谓?

            是否需要更快速度的检索和访问?

     

    到此结束了

            线程同步的集合的使用没有涉及,大家可以自行去MSDN学习,如有遗误,还请不吝指教。

            提供一个链接:http://msdn.microsoft.com/zh-cn/library/vstudio/7y3x785f.aspx。这也是本文的重要知识来源,大家也可以直接去此地址学习更多的东西。

     
     
    分类: .net
     
     
  • 相关阅读:
    课时作业
    第八周学习进度
    第一次nabcd编写
    第七周学习进度
    第六天进度
    第五天进度
    第四天进度
    第一篇
    1.Windows 系统下安装 IntelliJ IDEA
    Java开发环境(含IDE)的搭建
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3038515.html
Copyright © 2011-2022 走看看