利用Angularjs和bootstrap实现购物车功能


Posted in Javascript onAugust 31, 2016

先来看看效果图:

利用Angularjs和bootstrap实现购物车功能
购物车

一、代码

如果看了这个效果有兴趣想知道怎么做出来的话,那就继续往下看吧。话不多少,直接上代码。

html代码:

<!DOCTYPE html>
<html lang="en" ng-app="cart">
<head>
 <meta charset="UTF-8">
 <title>购物车</title>
 <link rel="stylesheet" href="../scripts/angular-1.4.0-rc.2/docs/components/bootstrap-3.1.1/css/bootstrap.min.css">
 <link rel="stylesheet" href="main.css">
</head>
<body ng-controller="cartCtr">
<table class="table table-hover" ng-show="items.length">
 <caption>AngularJS实现购物车</caption>
 <tr>
 <th>序号</th>
 <th>商品信息</th>
 <th>单价(元)</th>
 <th>数量</th>
 <th>金额(元)</th>
 <th>操作</th>
 </tr>
 <tr ng-repeat=" item in items">
 <td>{{$index + 1}}</td>
 <td><a href="{{item.linkUrl}}" target="_blank" title="此链接将跳转到淘宝相关页面...">{{item.title}}</a></td>
 <td class="bold">{{item.price|number:2}}</td>
 <td>
  <button type="button" class="btn btn-default btn-xs" ng-click="reduce(item.id)" ng-disabled="item.quantity<=1">-</button>
  <input type="text" size="5" ng-model="item.quantity" ng-keydown="quantityKeydown()" ng-keyup="quantityKeyup()">
  <button type="button" class="btn btn-default btn-xs" ng-click="add(item.id)">+</button>
 </td>
 <td class="bold mark">{{item.price*item.quantity|number:2}}</td>
 <td>
  <button type="button" class="btn btn-default btn-xs" ng-click="delete(item.id)">删除</button>
 </td>
 </tr>
</table>
<div class="empty" ng-show="!items.length">购物车空空,快去寻找宝贝</div>
<div class="total">
 已选商品:<span>{{getQuantites()}} </span>
 合计:
 <span class=" mark" ng-show="getTotalAmount()<15000">{{getTotalAmount()|number:2}}</span>
 <span class=" mark" ng-show="getTotalAmount()>=15000">
 {{getTotalAmount()*discount|number:2}}<span class="btn btn-xs">(9折)</span>
 <span class="discount">({{getTotalAmount()|number:2}})</span>
 </span>
 <button type="button" class="btn btn-primary btn-sm" ng-click="alertSubmit()">结 算</button>
</div>
<script src="../scripts/angular-1.4.0-rc.2/angular.js"></script><script src="app.js"></script>
</body>
</html>

js代码:

/ Created by wqq on 2016/5/25. /
var cartModule = angular.module('cart', []);
cartModule.controller('cartCtr', ['$scope', function ($scope) {
 $scope.discount = 0.9;
 $scope.items = [{id: 10001,title: "Web全栈工程师的自我修养 余果", price: 40.80,quantity: 2,linkUrl: "https://detail.tmall.com/item.htm?spm=a1z0d.6639537.1997196601.4.cwywJs&id=532166746631"},
     {id: 10002,title: "MacBook Pro Retina 15英寸", price: 16088.00,quantity: 1,linkUrl: "https://detail.tmall.com/item.htm?spm=a1z0d.6639537.1997196601.26.cwywJs&id=45771116847"},
     {id: 10003,title: "Surface Book I5 128G 独显",price: 11088.00, quantity: 1,linkUrl: "https://detail.tmall.com/item.htm?spm=a1z0d.6639537.1997196601.15.cwywJs&id=525614504276"},
     {id: 10004, title: "Lenovo Yoga3Pro I5 4G",price: 7299.00, quantity: 1,linkUrl: "https://detail.tmall.com/item.htm?spm=a1z0d.6639537.1997196601.37.cwywJs&id=41541519814"} ];
 $scope.add = function (id) {
  angular.forEach($scope.items, function (item, index, array) {
        if (item.id === id) {item.quantity++;} })
 };
 $scope.reduce = function (id) {
  angular.forEach($scope.items, function (item, index, array) {
        if (item.id === id) {item.quantity--; } })
 };
 //输入框添加keydown事件,避免输入非正整数
 $scope.quantityKeydown = function (event) {
  event = event || window.event;
  var target=event.target||event.srcElement;
  var keycode = event.keyCode;
  if ((37 <= keycode && keycode <= 40)||(48 <= keycode && keycode <= 57) || (96 <= keycode && keycode <= 105) || keycode == 8) {
    //方向键↑→ ↓←、数字键、backspace
  }
  else {
   console.log(keycode);
   event.preventDefault();
   return false;
  }
 };
//keyup事件,当输入数字为0时,重新刷新文本框内容
$scope.quantityKeyup = function (event) {
  event = event || window.event;
  var target=event.target||event.srcElement;
  var keycode = event.keyCode;
  if (48 === keycode || 96 === keycode ) {
   target.value=parseInt(target.value);
 }};
 //删除商品
 $scope.delete = function (id) {
  $scope.items.forEach(function (item, index) {
  if (item.id == id) {
   if (confirm("确定要从购物车中删除此商品?")) {
    $scope.items.splice(index, 1);
    return;
   }
  }
 })
 };
 //计算已选商品数量
 $scope.getQuantites = function () {
 var quantities = 0;
 angular.forEach($scope.items, function (item, index, array) {
  if (item.quantity) {
   quantities += parseInt(item.quantity);
  }
 });
 return quantities;
 };
 //计算合计总金额
 $scope.getTotalAmount = function () {
 var totalAmount = 0;
 angular.forEach($scope.items, function (item, index, array) {
  totalAmount += item.quantity * item.price;  });
 return totalAmount;
 };
 $scope.alertSubmit = function () {alert("Angular实现购物车"); }
}]);

二、分析

请忽略bootstrap的样式,我们只关注Angular,代码很简单,我们来简单的分析一下:

1. 准备

首先我们我们定义了一个cart模块、cartCtr控制器,并将它们引入到了html代码中,同时我们还在js中定义了一个数组items用于模拟购物车内的东西。

2. ng-repeat迭代器

为了将items里的数据动态的遍历加载出来,我们使用Angular里的内置指令ng-repeat,它可以非常方便的遍历数组,生成DOM元素,在这里循环生成了4个<tr>标签:

<tr ng-repeat=" item in items">

item就是items数组里面的某一个对象,是不是感觉这就是js中的for/in循环~~如果你是一名.net开发人员,用过asp.net mvc的Razor就对这种其他语言无缝操作DOM元素很熟悉了,至于java、PHP是否有没有类似的语法我就不清楚了,我是一名苦逼的.net开发。

利用Angularjs和bootstrap实现购物车功能
ng-repeat迭代器

我们可以看到第一个td中用到了$index,这是ng-repeat内的,并不是我们定义的,它的值是当前itemitems中的索引,从0开始,所以我们用$index+1作为序号,其他的还有(类似item.linkUrl)数据绑定。

我们在单价和金额两列用到了{{ xxx|number:2}},这是Angular中的一种过滤器,作用是将前面的值xxx保留两位小数,金额嘛,我们当然要精确一些。刚才说了这是一种过滤器,那就还有其他的,比如currency,可以在xxx前面添加一个$符号表示美元,可以自行百度其他过滤器用法。

3. 添加事件

当前界面上分别有数量+、-按钮、删除按钮,这几个事件都比较简单,利用ng-click给元素添加点击事件。通过传递某个商品的id,找到这个商品,对这个商品进行加、减、删除操作,只不过在“-”按钮上有添加了一个ng-disabled标签,根据名字我们就可以很容易想到html的disabled属性,它的作用就是当ng-disabled的值为true时DOM元素禁用,同理,下面用到的ng-show也是一样的,true时显示,false时隐藏。如果是数字的话会自动转化为boolean值,0是false,非0是true,注意负数也是true!。这里我让当数量为1时就不能减少了,因为再少就可以直接删除了呀~

然后在input元素添加ng-keydown事件,使其只能输入方向键↑→ ↓←、数字键、backspace。然后我试了下确实到达了目的,但是却可以输入类似“00021”这种数字,显然这并不能令人满意。我看了看淘宝的购物车,发现当在前面输入0时,这个文本框的内容会自动刷新,去掉前面的0,于是我又添加了ng-keyup事件:

$scope.quantityKeyup = function (event) {
  event = event || window.event; //兼容IE8以下,target也是
  var target=event.target||event.srcElement;
  var keycode = event.keyCode;
  if (48 === keycode || 96 === keycode ) {
   target.value=parseInt(target.value);
 }};

这时当我输入0时,文本框值就会自动刷新,为什么不添加到keydown里面而要另外再加一个事件呢?那是因为触发keydown事件时target.value的值还是原来的值,还没有包含本次输入的按键,而在keydown之后值就是新值了,这时候我们接着让触发keyup事件就可以达到目的了,可以对照看下淘宝购物车的效果,我觉得我的体验比它的更好,因为它只要不是在最后输入数字文本框总是会失去焦点。。。

4. 统计

统计数量就是直接绑定方法,遍历数组返回值。

合计金额这块,我做了个满15000打9折的设计。利用ng-show隐藏显示带打折信息的合计金额。

三、总结

js中用到了几处forEach遍历数组,ECMAScript5中原生的方法是array.forEach(function(item,index,array){});

angular中也封装了,angular.forEach(array,function(item,index,array){});

代码中我两种方法都用到了,也不知道那种性能好。。

至此,购物车就已经完成了,利用Angular的双向绑定,可以快速的实现数量、金额的联动改变。希望这篇文章的内容对大家学习和使用Angular能有所帮助,如果有疑问可以留言交流。

Javascript 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点)
Mar 10 Javascript
IE8 chrome中table隔行换色解决办法
Jul 09 Javascript
六款帮助你实现惊艳视差滚动效果的jQuery插件
Sep 14 Javascript
jquery与js函数冲突的两种解决方法
Sep 09 Javascript
canvas 弹幕效果(实例分享)
Jan 11 Javascript
angular实现form验证实例代码
Jan 17 Javascript
js以及jquery实现手风琴效果
Apr 17 Javascript
React实现全局组件的Toast轻提示效果
Sep 21 Javascript
spring+angular实现导出excel的实现代码
Feb 27 Javascript
Typescript的三种运行方式(小结)
Sep 18 Javascript
javascript 关于赋值、浅拷贝、深拷贝的个人理解
Nov 01 Javascript
解决vue组件没显示,没起作用,没报错,但该显示的组件没显示问题
Sep 02 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
Aug 31 #Javascript
基于JavaScript实现鼠标向下滑动加载div的代码
Aug 31 #Javascript
Node.js配合node-http-proxy解决本地开发ajax跨域问题
Aug 31 #Javascript
jQuery禁用快捷键例如禁用F5刷新 禁用右键菜单等的简单实现
Aug 31 #Javascript
基于JavaScript实现点击页面任何位置返回
Aug 31 #Javascript
jquery datatable服务端分页
Aug 31 #Javascript
关于javascript原型的修改与重写(覆盖)差别详解
Aug 31 #Javascript
You might like
PHP运行环境配置与开发环境的配置(图文教程)
2013/06/04 PHP
PHP缓冲区用法总结
2016/02/14 PHP
php转换上传word文件为PDF的方法【基于COM组件】
2019/06/10 PHP
php和js实现根据子网掩码和ip计算子网功能示例
2019/11/09 PHP
使用javascript获取flash加载的百分比的实现代码
2011/05/25 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
js二级地域选择的实现方法
2013/06/17 Javascript
5分钟理解JavaScript中this用法分享
2013/11/09 Javascript
Jquery如何实现点击时高亮显示代码
2014/01/22 Javascript
JavaScript的作用域和块级作用域概念理解
2014/09/21 Javascript
javascript实现查找数组中最大值方法汇总
2016/02/13 Javascript
javascript插件开发的一些感想和心得
2016/02/28 Javascript
JS图片左右无缝隙滚动的实现(兼容IE,Firefox 遵循W3C标准)
2016/09/23 Javascript
jQuery实现表格文本框淡入更改值后淡出效果
2016/09/27 Javascript
Javascript+CSS3实现进度条效果
2016/10/28 Javascript
bootstrap基本配置_动力节点Java学院整理
2017/07/14 Javascript
node.js中事件触发器events的使用方法实例分析
2019/11/23 Javascript
python抓取网页时字符集转换问题处理方案分享
2014/06/19 Python
跟老齐学Python之通过Python连接数据库
2014/10/28 Python
Python中优化NumPy包使用性能的教程
2015/04/23 Python
Python爬虫模拟登录带验证码网站
2016/01/22 Python
深入理解Django的中间件middleware
2018/03/14 Python
Python基于Twilio及腾讯云实现国际国内短信接口
2020/06/18 Python
pycharm进入时每次都是insert模式的解决方式
2021/02/05 Python
前端面试必备之html5的新特性
2017/09/05 HTML / CSS
HTML5上传文件显示进度的实现代码
2012/08/30 HTML / CSS
Lou & Grey美国官网:主打舒适性面料服饰
2017/12/21 全球购物
高中生的自我鉴定范文
2014/01/24 职场文书
成人继续教育实施方案
2014/03/01 职场文书
初中作文评语大全
2014/04/23 职场文书
大学生党员批评与自我批评范文
2014/10/14 职场文书
2014年卫生院工作总结
2014/12/03 职场文书
教师工作态度自我评价
2015/03/05 职场文书
党小组意见范文
2015/06/08 职场文书
原来实习报告是这样写的呀!
2019/07/03 职场文书
Python获取百度热搜的完整代码
2021/04/07 Python