angular--controller与service

韦修文
2023-12-01

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只去做和渲染视图有关的操作,而数据的操作应该由服务完成。理解有误的地方希望大家指正。

 类似资料: