avalonjs 实现简单购物车

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

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

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

    1、页面的Html结构

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< 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后可以定义了

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

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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
arr : [
   {
     id:1,
     num:1,
     price:45.5,
     text: '商品1'
   },
   {
     id:2,
     num:1,
     price:8.8,
     text: '商品2'
   }<span style= "font-size: 9pt; line-height: 1.5;" >]</span>

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

1
selected:[]


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

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

1
2
3
4
5
6
7
8
9
10
11
12
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(前面定义的属性)中删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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来找出对应的商品,这样才能计算该商品的金额。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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改变,则表示商品有被删除,需要重新计算总金额。

1
2
3
4
5
6
7
vm.selected.$watch( "length" , function (n) {
    vm.checkAllbool = n === vm.arr.size()
    vm.cal();
});
vm.arr.$watch( "length" , function (n) {
    vm.cal();
});

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<! 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值