利用Angularjs和bootstrap實(shí)現(xiàn)購(gòu)物車(chē)功能
先來(lái)看看效果圖:
購(gòu)物車(chē)
一、代碼
如果看了這個(gè)效果有興趣想知道怎么做出來(lái)的話(huà),那就繼續(xù)往下看吧。話(huà)不多少,直接上代碼。
html代碼:
<!DOCTYPE html> <html lang="en" ng-app="cart"> <head> <meta charset="UTF-8"> <title>購(gòu)物車(chē)</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實(shí)現(xiàn)購(gòu)物車(chē)</caption> <tr> <th>序號(hào)</th> <th>商品信息</th> <th>單價(jià)(元)</th> <th>數(shù)量</th> <th>金額(元)</th> <th>操作</th> </tr> <tr ng-repeat=" item in items"> <td>{{$index + 1}}</td> <td><a href="{{item.linkUrl}}" target="_blank" title="此鏈接將跳轉(zhuǎn)到淘寶相關(guān)頁(yè)面...">{{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">購(gòu)物車(chē)空空,快去尋找寶貝</div> <div class="total"> 已選商品:<span>{{getQuantites()}} </span> 合計(jì): <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()">結(jié) 算</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全棧工程師的自我修養(yǎng) 余果", 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 獨(dú)顯",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事件,避免輸入非正整數(shù) $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) { //方向鍵↑→ ↓←、數(shù)字鍵、backspace } else { console.log(keycode); event.preventDefault(); return false; } }; //keyup事件,當(dāng)輸入數(shù)字為0時(shí),重新刷新文本框內(nèi)容 $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("確定要從購(gòu)物車(chē)中刪除此商品?")) { $scope.items.splice(index, 1); return; } } }) }; //計(jì)算已選商品數(shù)量 $scope.getQuantites = function () { var quantities = 0; angular.forEach($scope.items, function (item, index, array) { if (item.quantity) { quantities += parseInt(item.quantity); } }); return quantities; }; //計(jì)算合計(jì)總金額 $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實(shí)現(xiàn)購(gòu)物車(chē)"); } }]);
二、分析
請(qǐng)忽略bootstrap的樣式,我們只關(guān)注Angular,代碼很簡(jiǎn)單,我們來(lái)簡(jiǎn)單的分析一下:
1. 準(zhǔn)備
首先我們我們定義了一個(gè)cart
模塊、cartCtr
控制器,并將它們引入到了html代碼中,同時(shí)我們還在js中定義了一個(gè)數(shù)組items
用于模擬購(gòu)物車(chē)內(nèi)的東西。
2. ng-repeat迭代器
為了將items
里的數(shù)據(jù)動(dòng)態(tài)的遍歷加載出來(lái),我們使用Angular里的內(nèi)置指令ng-repeat
,它可以非常方便的遍歷數(shù)組,生成DOM
元素,在這里循環(huán)生成了4個(gè)<tr>
標(biāo)簽:
<tr ng-repeat=" item in items">
item
就是items
數(shù)組里面的某一個(gè)對(duì)象,是不是感覺(jué)這就是js中的for/in
循環(huán)~~如果你是一名.net開(kāi)發(fā)人員,用過(guò)asp.net mvc的Razor就對(duì)這種其他語(yǔ)言無(wú)縫操作DOM
元素很熟悉了,至于java、PHP是否有沒(méi)有類(lèi)似的語(yǔ)法我就不清楚了,我是一名苦逼的.net開(kāi)發(fā)。
ng-repeat迭代器
我們可以看到第一個(gè)td中用到了$index
,這是ng-repeat
內(nèi)的,并不是我們定義的,它的值是當(dāng)前item
在items
中的索引,從0開(kāi)始,所以我們用$index+1
作為序號(hào),其他的還有(類(lèi)似item
.linkUrl
)數(shù)據(jù)綁定。
我們?cè)趩蝺r(jià)和金額兩列用到了{(lán){ xxx|number:2}},這是Angular中的一種過(guò)濾器,作用是將前面的值xxx保留兩位小數(shù),金額嘛,我們當(dāng)然要精確一些。剛才說(shuō)了這是一種過(guò)濾器,那就還有其他的,比如currency
,可以在xxx前面添加一個(gè)$符號(hào)表示美元,可以自行百度其他過(guò)濾器用法。
3. 添加事件
當(dāng)前界面上分別有數(shù)量+、-按鈕、刪除按鈕,這幾個(gè)事件都比較簡(jiǎn)單,利用ng-click
給元素添加點(diǎn)擊事件。通過(guò)傳遞某個(gè)商品的id,找到這個(gè)商品,對(duì)這個(gè)商品進(jìn)行加、減、刪除操作,只不過(guò)在“-”按鈕上有添加了一個(gè)ng-disabled
標(biāo)簽,根據(jù)名字我們就可以很容易想到html的disabled
屬性,它的作用就是當(dāng)ng-disabled
的值為true時(shí)DOM
元素禁用,同理,下面用到的ng-show
也是一樣的,true時(shí)顯示,false時(shí)隱藏。如果是數(shù)字的話(huà)會(huì)自動(dòng)轉(zhuǎn)化為boolean
值,0是false,非0是true,注意負(fù)數(shù)也是true!。這里我讓當(dāng)數(shù)量為1時(shí)就不能減少了,因?yàn)樵偕倬涂梢灾苯觿h除了呀~
然后在input元素添加ng-keydown
事件,使其只能輸入方向鍵↑→ ↓←、數(shù)字鍵、backspace
。然后我試了下確實(shí)到達(dá)了目的,但是卻可以輸入類(lèi)似“00021”這種數(shù)字,顯然這并不能令人滿(mǎn)意。我看了看淘寶的購(gòu)物車(chē),發(fā)現(xiàn)當(dāng)在前面輸入0時(shí),這個(gè)文本框的內(nèi)容會(huì)自動(dòng)刷新,去掉前面的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); }};
這時(shí)當(dāng)我輸入0時(shí),文本框值就會(huì)自動(dòng)刷新,為什么不添加到keydown
里面而要另外再加一個(gè)事件呢?那是因?yàn)橛|發(fā)keydown
事件時(shí)target.value
的值還是原來(lái)的值,還沒(méi)有包含本次輸入的按鍵,而在keydown
之后值就是新值了,這時(shí)候我們接著讓觸發(fā)keyup
事件就可以達(dá)到目的了,可以對(duì)照看下淘寶購(gòu)物車(chē)的效果,我覺(jué)得我的體驗(yàn)比它的更好,因?yàn)樗灰皇窃谧詈筝斎霐?shù)字文本框總是會(huì)失去焦點(diǎn)。。。
4. 統(tǒng)計(jì)
統(tǒng)計(jì)數(shù)量就是直接綁定方法,遍歷數(shù)組返回值。
合計(jì)金額這塊,我做了個(gè)滿(mǎn)15000打9折的設(shè)計(jì)。利用ng-show
隱藏顯示帶打折信息的合計(jì)金額。
三、總結(jié)
js中用到了幾處forEach
遍歷數(shù)組,ECMAScript5中原生的方法是array.forEach(function(item,index,array){});
angular中也封裝了,angular.forEach(array,function(item,index,array){});
代碼中我兩種方法都用到了,也不知道那種性能好。。
至此,購(gòu)物車(chē)就已經(jīng)完成了,利用Angular的雙向綁定,可以快速的實(shí)現(xiàn)數(shù)量、金額的聯(lián)動(dòng)改變。希望這篇文章的內(nèi)容對(duì)大家學(xué)習(xí)和使用Angular能有所幫助,如果有疑問(wèn)可以留言交流。
- 使用Angular.js實(shí)現(xiàn)簡(jiǎn)單的購(gòu)物車(chē)功能
- Angularjs 制作購(gòu)物車(chē)功能實(shí)例代碼
- Angular實(shí)現(xiàn)購(gòu)物車(chē)計(jì)算示例代碼
- angular和BootStrap3實(shí)現(xiàn)購(gòu)物車(chē)功能
- AngularJS 購(gòu)物車(chē)全選/取消全選功能的實(shí)現(xiàn)方法
- angular.js實(shí)現(xiàn)購(gòu)物車(chē)功能
- angularjs實(shí)現(xiàn)簡(jiǎn)單的購(gòu)物車(chē)功能
- AngularJS 實(shí)現(xiàn)購(gòu)物車(chē)全選反選功能
- AngularJs 終極購(gòu)物車(chē)(實(shí)例講解)
- Angular動(dòng)畫(huà)實(shí)現(xiàn)的2種方式以及添加購(gòu)物車(chē)動(dòng)畫(huà)實(shí)例代碼
相關(guān)文章
angular select 默認(rèn)值設(shè)置方法
下面小編就為大家?guī)?lái)一篇angular select 默認(rèn)值設(shè)置方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06AngularJS ng-change 指令的詳解及簡(jiǎn)單實(shí)例
本文主要介紹AngularJS ng-change 指令,這里對(duì)ng-change指令資料做了詳細(xì)介紹,并提供源碼和運(yùn)行結(jié)果,有需要的小伙伴參考下2016-07-07詳解Angular的內(nèi)置過(guò)濾器和自定義過(guò)濾器【推薦】
在實(shí)際的開(kāi)發(fā)過(guò)程中,很多后端返回給我們的數(shù)據(jù)都是需要格式化處理的,在angular中為我們內(nèi)置提供了filter指令,可以很方便的對(duì)數(shù)據(jù)進(jìn)行處理。本文將對(duì)Angular的內(nèi)置過(guò)濾器和自定義過(guò)濾器進(jìn)行詳細(xì)介紹,下面跟著小編一起來(lái)看下吧2016-12-12Angular 根據(jù) service 的狀態(tài)更新 directive
Angular JS (Angular.JS) 是一組用來(lái)開(kāi)發(fā)Web頁(yè)面的框架、模板以及數(shù)據(jù)綁定和豐富UI組件。本文給大家介紹Angular 根據(jù) service 的狀態(tài)更新 directive,需要的朋友一起學(xué)習(xí)吧2016-04-04Angular?Component屬性綁定target和attr.target的區(qū)別分析
這篇文章主要介紹了Angular?Component屬性綁定target和attr.target的區(qū)別分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07詳解AngularJS controller調(diào)用factory
本篇文章主要介紹了詳解AngularJS controller調(diào)用factory,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05Angularjs 實(shí)現(xiàn)動(dòng)態(tài)添加控件功能
這篇文章主要介紹了Angularjs 實(shí)現(xiàn)動(dòng)態(tài)添加控件功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-05-05Angular 4.x+Ionic3踩坑之Ionic3.x pop反向傳值詳解
這篇文章主要給大家介紹了關(guān)于Angular 4.x+Ionic3踩坑之Ionic3.x pop反向傳值的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03