AngularJS中的控制器是一个函数,用来向视图的作用域中添加额外的功能。我们用它来给
作用域对象设置初始状态,并添加自定义行为。
服务提供了一种能在应用的整个生命周期内保持数据的方法,它能够在控制器之间进行通
信,并且能保证数据的一致性。服务是一个单例对象,在每个应用中只会被实例化一次(被$injector实例化),并且是延迟
加载的(需要时才会被创建)。服务提供了把与特定功能相关联的方法集中在一起的接口。
记录一下自己边学边做,写的一个小例子:
首先是html代码:
<link href="./shopcart.css" rel="stylesheet" />
<script src="../angular-1.7.8/angular.js"></script>
<script src="../angular-1.7.8/angular-animate.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/angularjs-toaster/1.1.0/toaster.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angularjs-toaster/1.1.0/toaster.min.js"></script>
<div class="container" ng-controller="shopController">
<div class="shopCart">
<div ng-repeat="item in shopCartData" class="shopItem">
<span>商品名称:{{item.name}}</span>
<span>商品描述:{{item.des | overflow}} </span>
<span>商品单价:¥{{item.price}}</span>
<span>购买数量:{{item.num}}</span>
<span>总价:{{item.price * item.num}} </span>
<button ng-click="deleteFromCart($index, item.id, item.num)">从购物车删除</button>
</div>
<div class="shopItem space">购物车总价:{{totalPrice}}</div>
</div>
<div class="shop">
<div ng-repeat="item in shopData" class="shopItem" ng-show="item.task">
<span>商品名称:{{item.name}}</span>
<span>商品描述:{{item.des | overflow}} </span>
<span>商品库存:{{item.task}}</span>
<span>商品单价:¥{{item.price}}</span>
<div class="changeNum">
<button ng-click="reduce($index)">-</button>
<input type="text" ng-model="item.num" value="item.num" name="num"/>
<button ng-click="add($index)">+</button>
<button ng-click="addToShopCart($index)" ng-disabled="item.num == 0">添加到购物车</button>
</div>
</div>
</div>
</div>
<!-- 这个指令放在当前页面就行,没有这个是没有特效的,他是特效的容器 -->
<!--
close-button: 显示关闭按钮
animation-class: 出现位置
limit:允许出现的条数
newest-on-top: 把最新的信息放在最上面显示
position-class: 'toast-top-full-width': 在上面出现一排
-->
<toaster-container toaster-options="{
'close-button': true,
'animation-class': 'toast-top-center',
'limit':1,
'newest-on-top':false,
}"></toaster-container>
用到的内置指令如下:
ng-controller 声明控制器
ng-repeat 循环输出
ng-show 是否显示
ng-click 点击事件
ng-modal 绑定数据
js代码:
var app = angular.module("myApp", ['toaster', 'ngAnimate']);
app.service('getDataService', function () {
//模拟数据
this.shopData = [{
id: '0',//商品id
name: '茶杯',//商品名称
des: '茶杯茶杯茶杯茶杯茶杯茶杯茶杯茶杯茶杯',//商品描述
task: '12',//商品库存
price: '18',//商品单价
}, {
id: '1',//商品id
name: '笔记本',//商品名称
des: '笔记本笔记本笔记本笔记本笔记本笔记本',//商品描述
task: '46',//商品库存
price: '3',//商品单价
}, {
id: '2',//商品id
name: '卫生纸',//商品名称
des: '卫生纸卫生纸卫生纸卫生纸卫生纸卫生纸卫生纸卫生纸卫生纸',//商品描述
task: '26',//商品库存
price: '6',//商品单价
}, {
id: '3',//商品id
name: '垃圾袋',//商品名称
des: '垃圾袋垃圾袋垃圾袋垃圾袋垃圾袋垃圾袋垃圾袋垃圾袋垃圾袋',//商品描述
task: '21',//商品库存
price: '2.5',//商品单价
}, {
id: '4',//商品id
name: '茶叶',//商品名称
des: '茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶茶叶',//商品描述
task: '8',//商品库存
price: '354',//商品单价
}]
this.getShopData = function () {
return this.shopData;
}
this.deleteTask = function (id, num) {
if (this.shopData[id].task < num) {
return {
code: '201',
msg: '库存不足。',
}
} else {
this.shopData[id].task -= num;
console.log('库存减少');
return {
code: '200',
msg: '修改库存成功'
}
}
}
this.addTask = function (id, num) {
this.shopData[id].task += num;
return {
code: '200',
msg: '修改库存成功'
}
}
})
app.controller("shopController", ['$scope', 'getDataService', 'toaster',
function ($scope, getDataService, toaster) {
//从service中获取数据
$scope.shopData = getDataService.getShopData();
//用来放购物车商品的数组
$scope.shopCartData = [];
//购物车内所有商品的总价
$scope.totalPrice = 0;
//为每个商品添加上用来控制购买数量的字段
$scope.shopData.forEach(element => {
element.num = 0;
});
//减少购买数量
$scope.reduce = function (index) {
if ($scope.shopData[index].num <= 0) {
toaster.pop('error', "", "已经是0了,不能在减少了");
} else {
$scope.shopData[index].num--;
}
}
//添加购买数量
$scope.add = function (index) {
if ($scope.shopData[index].task <= $scope.shopData[index].num) {
toaster.pop('error', "", "没有那么多库存");
} else {
$scope.shopData[index].num++;
}
}
/*
加入到购物车
1.判断当前商品是否已经存在购物车内
2.如果已经存在,则购物车该商品数量增加,购物车总价增加
3.如果不存在,则向购物车内添加元素,购物车总价增加
*/
$scope.addToShopCart = function (index) {
//默认购物车数组内是不存在商品的
var boo = false;
//去服务里面查询库存是否足够
var res = getDataService.deleteTask($scope.shopData[index].id, $scope.shopData[index].num);
//200表示足够,201表示不足
if (res.code == '200') {
$scope.shopCartData.forEach(item => {
//在这里判断是否存在
if (item.id == $scope.shopData[index].id) {//使用indexof也可以
boo = true;
item.num += $scope.shopData[index].num;
$scope.totalPrice += $scope.shopData[index].num * $scope.shopData[index].price;
toaster.pop('success', "", "添加至购物车成功");
}
})
// 在这里判断不存在
if (!boo) {
$scope.shopCartData.push(JSON.parse(JSON.stringify($scope.shopData[index])));
$scope.totalPrice += $scope.shopData[index].num * $scope.shopData[index].price;
toaster.pop('success', "", "添加至购物车成功");
}
} else if (res.code == '201') {
toaster.pop('error', "", res.msg);
}
//添加至购物车之后,将商品列表内的该商品购买数量清0
$scope.shopData[index].num = 0;
}
//从购物车删除商品
$scope.deleteFromCart = function (idx, id, num) {
//由服务去修改库存
var res = getDataService.addTask(id, num);
if (res.code == '200') {
//修改总价
$scope.totalPrice -= $scope.shopCartData[idx].num * $scope.shopCartData[idx].price;
//从购物车数组内移除
$scope.shopCartData.splice(idx, 1);
toaster.pop('success', "", "删除成功");
}
}
//为输入框添加监听器
for(let i = 0; i < $scope.shopData.length; i++){
//newValue代表刚刚输入的值,oldValue代表变化之前的值
$scope.$watch("shopData["+i+"].num",function(newValue, oldValue){
//输入框为值为空时显示0,
if(newValue == ''){
$scope.shopData[i].num = 0;
}
//使用键盘修改时,去除掉最前面的0,
if(typeof(newValue) == 'string'){
if(newValue[0] == '0'){
$scope.shopData[i].num = newValue.substr(-(newValue.length-1));
}
//如果输入的值大于库存,则值不发生改变
if(parseInt($scope.shopData[i].num) > $scope.shopData[i].task){
toaster.pop('error', "", "没有那么多库存");
$scope.shopData[i].num = oldValue;
}
}
},true)
}
}
])
//为描述添加过滤
app.filter('overflow', function () {
return function (val) {
if (val) {
return val.substr(0, 20) + '...';
}
};
});
我理解的就是,controller只去做和渲染视图有关的操作,而数据的操作应该由服务完成。理解有误的地方希望大家指正。