AngularJS入门笔记-9-购物网站-添加购物车和路由功能
一个网站不可能只在一个html文件就完成了的,一般都有多个html文件以及多个不同的组件或者模块,这就需要后端定义路由(即url地址)与组件代码片段,而AngularJS有一个路由的插件可以将路由功能放在前端完成,同时提供了组件功能,在上一个篇的基础上,本次加上路由功能和购物车。
接上一篇:AngularJS入门笔记-8-静态购物网站产品列表Demo
有添加到购物车功能后的产品列表界面效果如下图:
购物车界面如下图:
目录组织结构:
1 | angularjs #项目目录 |
应用入口app.html
随着应用的功能增加,逻辑变的复杂许多,html元素更是错综复杂,没办法一下弄清楚每个元素完成的功能,此时需要将这些标签拆分,使用ng-include指令在运行时引入这些局部视图。
使用局部视图有如下好处:
- 将应用拆分为可独立管理的块
- 在应用范围内的可复用性
- 易于与不同的路由url结合,修改对应的视图
1 |
|
全局模块-公用控制器 sportsStore.js
将模型修改为通过后端服务器获取1
2
3
4
5
6
7
8
9
10
11
12
13
14angular.module("sportsStore")
.constant("dataUrl", "products.json") // 定义常量,此处的products.json可以改为某个url接口
.controller("sportsStoreCtrl", function ($scope, $http, dataUrl) {
$scope.data = {};
// 使用http服务将模型加载到应用内
$http.get(dataUrl)
.success(function (data) {
$scope.data.products = data;
})
.error(function (error) { // 当加载数据出错时显示提示信息
$scope.data.error = error;
});
});
products.json
此json数据多了一个id字段标识每一种产品,当加入购物车时以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[{
"id": "ID1",
"name": "Product #1",
"description": "A product",
"category": "Category #1",
"price": 100
},
{
"id": "ID2",
"name": "Product #2",
"description": "A product",
"category": "Category #1",
"price": 110
},
{
"id": "ID3",
"name": "Product #3",
"description": "A product",
"category": "Category #2",
"price": 210
},
{
"id": "ID4",
"name": "Product #4",
"description": "A product",
"category": "Category #3",
"price": 202
}]
产品列表视图 productList.html
将产品列表部分从app.html中抽离出,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<div class="panel panel-default row" ng-controller="productListCtrl"
ng-hide="data.error">
<div class="col-xs-3">
<a ng-click="selectCategory()"
class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in data.products | orderBy:'category' | unique:'category'"
ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"
ng-class="getCategoryClass(item)">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well"
ng-repeat="item in data.products | filter:categoryFilterFn | range:selectedPage:pageSize">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<!-- 添加产品到购物车按钮 -->
<button ng-click="addProductToCart(item)"
class="btn btn-success pull-right">
Add to cart
</button>
<span class="lead">{{item.description}}</span>
</div>
<div class="pull-right btn-group">
<a ng-repeat="page in data.products | filter:categoryFilterFn | pageCount:pageSize"
ng-click="selectPage($index + 1)" class="btn btn-default"
ng-class="getPageClass($index + 1)">
{{$index + 1}}
</a>
</div>
</div>
</div>
购物车模块/服务 cart.js
比如购物车这样独立的功能可以将其放在组件文件夹内,而不是将其控制器和视图放在公共区域,
在新模块cart中自定义服务,使用factory方法,传入服务的名称和函数,工厂模式将在该服务需要时被调用(而不是应用一开始就被调用),通过这个工厂函数只调用一次。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
64angular.module("cart", [])
.factory("cart", function () {
var cartData = [];
return {
// 添加指定的产品到购物车,若购物车已包含该产品,则增加数量
addProduct: function (id, name, price) {
var addedToExistingItem = false;
for (var i = 0; i < cartData.length; i++) {
if (cartData[i].id == id) {
cartData[i].count++;
addedToExistingItem = true;
break;
}
}
if (!addedToExistingItem) {
cartData.push({
count: 1, id: id, price: price, name: name
});
}
},
// 删除指定的产品
removeProduct: function (id) {
for (var i = 0; i < cartData.length; i++) {
if (cartData[i].id == id) {
cartData.splice(i, 1);
break;
}
}
},
// 返回购物车中所有产品
getProducts: function () {
return cartData;
}
}
})
// 创建一个购物车结算指令,该指令能在多个页面中复用
.directive("cartSummary", function (cart) { // 自定义指令需要传入两个参数,一个为指令名称,一个为指令执行时调用的工厂函数
return { // 返回一个对象,该对象定义了指令的各种属性
restrict: "E", // 以元素标签的形式调用该指令(可简单的当做是自定义的html标签即可)
templateUrl: "components/cart/cartSummary.html", // 指定指令的局部视图,即完成后的html元素内容
controller: function ($scope) { // 指定该指令的局部控制器
var cartData = cart.getProducts();
// 计算总价
$scope.total = function () {
var total = 0;
for (var i = 0; i < cartData.length; i++) {
total += (cartData[i].price * cartData[i].count);
}
return total;
}
// 计算产品的总量
$scope.itemCount = function () {
var total = 0;
for (var i = 0; i < cartData.length; i++) {
total += cartData[i].count;
}
return total;
}
}
};
});
购物车统计总价和总量视图 cartSummary.html
1 | <style> |
购物车控制器 checkoutControllers.js
1 | angular.module("sportsStore") |
购物车视图 checkoutSummary.html
1 | <h2>Your cart</h2> |