• avalonjs 实现简单购物车


        因为最近有在做购物车,然后我们是用avalon来实现一些模块的,所以顺其自然的用avalon来实现购物车,目前发现avalon还是比较强大的,大大的节约了代码量。

        购物车一般具备的功能是加减数量、选择商品、删除商品和计算金额,因为avalon具有双向绑定功能,所以杜绝了dom的操作,只需要完成功能的逻辑即可,可以分下面几个步骤实现。

      runjs: http://runjs.cn/detail/1dnkgxom

        1、页面的Html结构

        这里不考虑好的效果,所以直接用最简单的html来实现了,主要包含控制器,列表循环,金额显示,简单代码结构如下

    <body ms-controller="test">
            <ul ms-visible="arr.length">
                <li><input type="checkbox" ms-click="checkAll" ms-duplex-checked="checkAllbool"/>全选</li>
                <li ms-repeat="arr" >
                    <input type="checkbox" ms-attr-value="el.id" ms-duplex="selected" />
                    {{el.text}}
                    <input type="text" name="" ms-attr-value="el.num" ms-on-input="changeNum(el)">
                    <a href="javascript:;" ms-click="plus(el)">加</a>
                    <a href="javascript:;" ms-click="minus(el)">减</a>
                    <a href="javascript:;" ms-click="del(el)">删除</a>
                    <p>单价:{{el.price | currency}}</p>
                    <p>金额:{{el.num*el.price | currency}}</p>
                </li>
            </ul>
            <p>总金额:{{total | currency}}</p>
        </body>

         这里有全选、加减、删除几个功能事件,金额用了过滤器currency。


        2、引入avalon.js,定义模型

        引入js是必须的,那么引入avalon.js后可以定义了

    var vm = avalon.define({
                    $id: "test"
    });

        这样就定义了一个简单的模型,$id传入的是控制器的值,本文例子的控制器是写在body,如果不理解可以去看看官网。


        3、定义购物车里面的商品

        实际项目中,这个肯定是通过后台获取到的,这里为了演示就直接定义了,从第一点的html结构可以看出来,这里购物车的商品用的是arr,所以接着定义的就是arr,可以这样定义

    arr : [
      {
        id:1,
        num:1,
        price:45.5,
        text:'商品1'
      },
      {
        id:2,
        num:1,
        price:8.8,
        text:'商品2'
      }]

        这里就定义两个用来测试,那么还需要一个值来保存选中的商品id,这里给模型增加一个selected属性,类型为数组

    selected:[]


        4、定义全选的模型和方法

        购物车里面一般都有全选的功能的,只是表现的形式不一样,那么可以这么定义

    checkAllbool : false,
    checkAll : function() {
          if (this.checked) {
                var _arr = [];
                avalon.each(vm.arr,function(index,item){
                     _arr[index] = item.id+'';
                });
                vm.selected = _arr;
          } else {
               vm.selected=[];
          }
    }

        通过checkAllbool属性来实现和判断是否选中“全选”,通过checkAll来实现选中全部或者取消选中全部,其实就是修改模型里面的selected属性,如果selected为空数组则没有一个是选中的,如果那个需要选中只需要把对应的值放到selected数组中即可,因为在html中checkbox使用 ms-duplex 进行绑定的,而绑定的是 selected属性。

         4、定义加、减、删除的方法

          加减主要是数量上的变化,而删除则是需要把该商品直接从arr(前面定义的属性)中删除

    plus: function(el){
       el.num++;
       vm.cal();
     },
    minus: function(el){
       if(el.num>1){
           el.num--;
           vm.cal();
       }
    },
    del: function(el){
        vm.arr.remove(el);
    },
    changeNum: function(el){
        var _value = this.value,
            _reg = /^[1-9]d?$/
        ;
        if(!_reg.test(_value)){
            this.value = 1;
            el.num = 1;
        }else{
            el.num = _value;
        }
    
        vm.cal();
    }

        这里还有一个是当输入框改变时执行的方法,这里通过出入对象来进行操作,可以看看第一步中的html代码,就明白了,无论是改变还是加减都最后要执行 vm.cal,vm.cal是计算总金额的,将在下面讲解。

        加减的方法都很简单主要是修改num属性即可,changeNum则增加了正则判断,判断输入的是否为数字。


        5、定义计算总金额

        计算总金额的方法很简单,就是把所有选中的商品的数量乘以单价再加起来,但是这里面涉及到另一个方法,那就是通过商品的id来找出对应的商品,这样才能计算该商品的金额。

    total:0,
    cal: function(){
        var _arr = this.arr,
            _selected = this.selected,
            i = 0,
            _obj = '',
            _prcie = 0
        ;
        if(_selected.length){
            for(;i<_selected.length;i++){
                _obj = this.findById(_selected[i]) ||{};
                if(_obj.price &&  _obj.num){
                      _prcie = _prcie + _obj.price * _obj.num;
                }
            }
        }
                        
        this.total = _prcie;
    
    },
    findById: function(id){
        if(!id) return '';
            var i=0,
                _arr = this.arr,
                _obj = '',
                _id = parseInt(id,10)
            ;
    
            for(;i<_arr.length;i++){
                 if(_arr[i].id === _id){
                     _obj = _arr[i];
                 }
            }
    
            return _obj;
    }



        这里面主要用的是循环,找到商品的对象然后计算商品的金额再相加,代码略长。


        6、监听属性

        需要监听两个属性,那就是 selected 和 arr,监听 selected是为了随时了解商品有没有全选中,主要通过监听Length。监听arr是判断商品有没有被删除,如果arr的length改变,则表示商品有被删除,需要重新计算总金额。

    vm.selected.$watch("length", function(n) {
       vm.checkAllbool = n === vm.arr.size()
       vm.cal();
    });
    vm.arr.$watch("length", function(n) {
       vm.cal();
    });

        通过上面的步骤分析,可以了解了大概的实现流程,下面是完整的代码。

    <!DOCTYPE html>
    <html>
        <head>
            <title>购物车</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 
            <script src="../avalon.js" ></script>
            <script>
                var vm = avalon.define({
                    $id: "test",
                    arr : [
                        {
                            id:1,
                            num:1,
                            price:45.5,
                            text:'商品1'
                        },
                        {
                            id:2,
                            num:1,
                            price:8.8,
                            text:'商品2'
                        }
                    ],
                    selected : ["1"],
                    checkAllbool : false,
                    checkAll : function() {
                        if (this.checked) {
                            var _arr = [];
                            avalon.each(vm.arr,function(index,item){
                                _arr[index] = item.id+'';
                            });
                            vm.selected = _arr;
                        } else {
                            vm.selected=[];
                        }
                    },
                    plus: function(el){
                        el.num++;
                        vm.cal();
                    },
                    minus: function(el){
                        if(el.num>1){
                            el.num--;
                            vm.cal();
                        }
                    },
                    del: function(el){
                        vm.arr.remove(el);
                    },
                    changeNum: function(el){
                        var _value = this.value,
                            _reg = /^[1-9]d?$/
                        ;
                        if(!_reg.test(_value)){
                            this.value = 1;
                            el.num = 1;
                        }else{
                            el.num = _value;
                        }
    
                        vm.cal();
                    },
                    total:0,
                    cal: function(){
                        var _arr = this.arr,
                            _selected = this.selected,
                            i = 0,
                            _obj = '',
                            _prcie = 0
                        ;
                        if(_selected.length){
                            for(;i<_selected.length;i++){
                                _obj = this.findById(_selected[i]) ||{};
    
                                if(_obj.price &&  _obj.num){
                                    _prcie = _prcie + _obj.price * _obj.num;
                                }
                            }
                        }
                        
                        this.total = _prcie;
    
                    },
                    findById: function(id){
                        if(!id) return '';
                        var i=0,
                            _arr = this.arr,
                            _obj = '',
                            _id = parseInt(id,10)
                        ;
    
                        for(;i<_arr.length;i++){
                            if(_arr[i].id === _id){
                                _obj = _arr[i];
                            }
                        }
    
                        return _obj;
                    }
                });
                vm.selected.$watch("length", function(n) {
                    vm.checkAllbool = n === vm.arr.size()
                    vm.cal();
                });
                vm.arr.$watch("length", function(n) {
                    vm.cal();
                });
                vm.cal();
            </script>
        </head>
        <body ms-controller="test">
            <ul ms-visible="arr.length">
                <li><input type="checkbox" ms-click="checkAll" ms-duplex-checked="checkAllbool"/>全选</li>
                <li ms-repeat="arr" >
                    <input type="checkbox" ms-attr-value="el.id" ms-duplex="selected" />
                    {{el.text}}
                    <input type="text" name="" ms-attr-value="el.num" ms-on-input="changeNum(el)">
                    <a href="javascript:;" ms-click="plus(el)">加</a>
                    <a href="javascript:;" ms-click="minus(el)">减</a>
                    <a href="javascript:;" ms-click="del(el)">删除</a>
                    <p>单价:{{el.price | currency}}</p>
                    <p>金额:{{el.num*el.price | currency}}</p>
                </li>
            </ul>
            <p>总金额:{{total | currency}}</p>
        </body>
    </html>


        用avalon时间还不久,一步步来,希望能更深入了解mvvm框架,在后面的日子里应用更多的场景。

        本文同时发布在我的个人博客 http://www.subying.com/archives/131.html





  • 相关阅读:
    P7473 [NOI Online 2021 入门组] 重力球
    CF896D Nephren Runs a Cinema
    [持续更新]一些有趣的数学问题
    [微积分与无穷级数]AMM Problems笔记
    [补题]SWERC-2018
    [补题]Asia Regional Contest, Tokyo, 2014

    [NOI2005]瑰丽华尔兹-单调队列优化DP
    [补题]2017多校D-BD-区间筛/二分+线段树
    [补题]2017多校5A/HDU6085-Rikka with Candies-bitset优化
  • 原文地址:https://www.cnblogs.com/subying/p/4621063.html
Copyright © 2020-2023  润新知