【问题标题】:updating data between controller, service and directive在控制器、服务和指令之间更新数据
【发布时间】:2014-10-10 22:01:23
【问题描述】:

我编写了一个非常简单的测试应用程序,如下所示:

angular.module('tddApp', [])

.controller('MainCtrl', function ($scope, $rootScope, BetslipService) {
    $scope.displayEvents = [
        {
            id: 1,
            name: 'Belarus v Ukraine',
            homeTeam: 'Belarus',
            awayTeam: 'Ukraine',
            markets: {home: '2/1', draw: '3/2', away: '5/3'},
            display: true
        }
    ];
    $scope.betslipArray = BetslipService.betslipArray;
    $scope.oddsBtnCallback = BetslipService.addToBetslip;
    $scope.clearBetslip = BetslipService.clearBetslip;
})

.directive('oddsButton', function () {
    return {
        template: '<div class="odds-btn">{{market}}</div>',
        replace: true,
        scope: {
            market: '@',
            marketName: '@',
            eventName: '@',
            callback: '&'
        },
        link: function (scope, element) {

            element.on('click', function() {
                scope.callback({
                    name: scope.eventName,
                    marketName: scope.marketName,
                    odds:scope.market
                });
            });
        }
    };
})

.factory ('BetslipService', function ($rootScope) {
    var rtnObject = {};

    rtnObject.betslipArray = [];

    rtnObject.addToBetslip = function (name, marketName, odds) {
        rtnObject.betslipArray.push({
            eventName: name,
            marketName: marketName,
            odds: odds
        });
    };

    rtnObject.clearBetslip = function () {
        rtnObject.betslipArray = [];
    };

    return rtnObject;
});

我已将一个数组分配给一个控制器变量。我还分配了修改数组的函数。要将对象添加到数组,回调由具有隔离范围的指令调用。发生了一些我不太明白的奇怪行为:

=> 单击指令会在服务中运行回调。我已经进行了一些调试,似乎控制器变量已更新,但未显示在 html 中。 => 单击按钮清除数组未按预期工作。第一次导致元素显示,之后就没有效果了。

我认为这可能与嵌套的 ng-repeats 创建自己的范围有关

注意

我通过将服务中的函数更改为:

while (rtnObject.betslipArray.length > 0) {
    rtnObject.betslipArray.pop();
}
// instead of 
rtnObject.betslipArray = [];

这是有道理的,因为服务变量被指向一个新对象,而旧的引用将保留在控制器中。

我通过将回调调用包装在 scope.$apply() 中的指令中来更新 html。 这部分我真的不明白。当指令具有隔离作用域时,指令中调用的 scope.$apply() 如何对控制器作用域产生影响?更新小提琴:http://jsfiddle.net/b6ww0rx8/7/

任何想法都非常感谢

jsfiddle:http://jsfiddle.net/b6ww0rx8/5/

C

【问题讨论】:

  • 我实际上在您的服务中添加了一些console.log 语句,并在您的控制器中为阵列添加了一条监视语句,我发现您的控制器阵列没有被更新。服务中的数组是但不是控制器。
  • 我做了类似的测试。我不确定为什么 $watch 没有选择这个,但是如果我将控制器范围分配给服务中的一个变量并按照jsfiddle.net/b6ww0rx8/6 记录它,看起来控制器正在更新
  • 您正在添加资源和耗时的 while 循环以截断您的数组?最重要的是,您在阵列上使用pop() 以完全删除项目,这也有成本? array.length = 0,一行没有循环,没有时间浪费。如果您碰巧在该数组中有数千个项目会发生什么?您的 while 循环可能会花费太长时间并挂起您的应用程序。

标签: angularjs


【解决方案1】:

我在这里工作:http://jsfiddle.net/b6ww0rx8/8/

添加了$q$scope.$emit$timeout 子句以帮助您的指令/服务和控制器之间的通信。

我还想说,我不会将服务函数分配给控制器$scope, 你应该在控制器中定义调用服务函数的函数。

而不是这个:

$scope.clearBetslip = BetslipService.clearBetslip;

这样做:

$scope.clearBetslip = function(){
    BetslipService.clearBetslip().then(function(){
        $scope.betslipArray = BetslipService.getBetslipArray();
    });
};

【讨论】:

  • 我不确定我是否同意你的看法。当然,角度方式是从控制器中抽象出尽可能多的逻辑。将服务方法分配给 $scope 变量有什么问题?
  • 好吧,这个页面上的例子。您会遇到问题,您认为您有对数组的引用,并且虽然它在服务中更新,但在控制器中却没有更新。反过来,将此示例中的 clear 函数直接分配给控制器范围不允许控制器在 clear 执行后更新数组,这是您不想在服务内部执行的操作,因为服务不应该关心控制器的变量。
  • 服务应该检索、保存/发送、操作数据并为其提供逻辑,这样是的,您是正确的,服务将逻辑从控制器中抽象出来。但是控制器应该知道如何使用该服务,我上面的示例绝不会向控制器添加额外的逻辑。控制器只调用一个服务方法来操作数据并等待服务完成,如果成功则更新控制器的数组,以便我们可以相应地更新显示。承诺中涉及的逻辑非常少,在这种情况下是适当的。
  • 这不是由在控制器中引用服务变量引起的。当我将一个新数组分配给服务中的变量时,清除不起作用。这意味着控制器和服务不再指向同一个对象。仅当从指令范围调用回调时才会出现添加项目的问题,将此调用包装在范围中。$apply 解决了
  • 这就是问题所在。如果您要使用其他人的服务,为了争论,这与您在这里所做的相同,在明确将内部服务的数组分配给一个全新的数组后,您的控制器不再引用您的数组需要从服务。因此,服务的数组最好是私有的,就像在类对象中一样,并且您调用 getter 来对控制器的数组进行更改。
猜你喜欢
  • 1970-01-01
  • 2013-08-14
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多