这是我的angularJS应用程序的正确方法吗?

时间:2014-08-21 02:52:57

标签: angularjs service scope

我正在学习AngularJS,而且我并不完全确定这是我正在尝试做的事情的正确方法。

我想创建一个可重用的库,它将使用指令显示作用域中的数据,该指令将使用模板。

我是怎么想的,我如何使用服务将新数据传达给范围?

我创造了一个简单的plunker来说明我想要做的事情。

http://plnkr.co/edit/Y18EzatGYpYPE9MHdVgL?p=info

该服务似乎没有遵循正确的角度模式。我不认为我应该将$ scope传递给服务来更新它,但是,我想保持用户隐藏脏信息。用户甚至不必知道$ scope上有.dataList对象。

dataListApp.service('ngDataListSvc', function() {
  this.init = function($scope) {
    // Pretend this is coming from a database
    $scope.dataList.data = [{Id: 1, Name: 'Fred'}, { Id: 2, Name: 'Barney'}, { Id: 3, Name: 'Bam'}];
    console.log($scope.dataList);
  } 

  this.refresh = function($scope) {
    // Pretend this is coming from a database
    $scope.dataList.data = [{Id: 4, Name: 'Wilma'}, { Id: 5, Name: 'Betty'}, { Id: 6, Name: 'Pebbles'}];
  }
});

在此方案中修改范围的最佳方法是什么?有没有办法使用只能由服务和指令封装的范围,但是其他人不能访问它?

2 个答案:

答案 0 :(得分:1)

您可以随时随地调用任何内容......但要做到正确,您需要引用与一起使用的数据和应该调用它的上下文。一般来说,这比听起来要棘手得多。

你遇到的问题是你有一个与AngularJS建立不同的哲学。在MVC(或MVW)中,Controller的主要目的是执行您要避免的操作:充当后端服务和数据模型(M)与前端UI(V)之间的联络人它们渲染它们并处理用户交互。它们基本上是 的地方,你可以“连接”这些元素。因此,通过尝试避免将它们连接到那里,你基本上是在说你不想要框架主要在那里给你的能力 - 一个好的问题是不同的框架是否更适合你

如果你绝对致力于这样做,那说解决问题真的不是那么难。一个简单的选择是使一个简单的属性指令使具有'隔离范围'(根本不定义范围属性)。您可以在放置ng-controller属性的同一DOM元素上应用此指令。那么该指令将具有与控制器本身相同的$ scope,可以向注入器询问您想要获取数据的服务,并且可以处理这些定义。

我修改了你的Plunkr以说明基本概念: http://plnkr.co/edit/aT9m4GtFzCsnAEd8k7xR?p=preview

你基本上是在做一个简单的指令并在那里连接'魔术':

app.directive('addMyService', ['ngDataListSvc', function(ngDataListSvc) {
  return {
    restrict: 'A',
    link: function($scope) {
      $scope.init = function() {
        ngDataListSvc.init($scope);
      }

      $scope.refresh = function() {
        ngDataListSvc.refresh($scope);
      }
    }
  }
}]);

如果你想要一个关于这种魔术的好例子,请看一下ngBindOnce,一个非常酷的模块Pasquale Vazzanna(一个非常有才华的AngularJS开发人员)写道,让你尽量减少你拥有的手表数量大数据模型。可以应用于单个元素的属性,以及应用于主容器元素的属性,这些属性提供了执行其工作所需的包装器“魔术”。如果你想通过AngularJS指令获得超级创意,这是一个非常好的例子。

答案 1 :(得分:0)

我决定做的更多的是......

在我的指令中,我创建了一个控制器并在那里添加了页面控制器可以调用的函数。

dataListApp.directive('ngDatalist', ['$compile', '$window', 'ngDataListSvc', function ($compile, $window, ngDataListSvc) {
    return {
        restrict: 'E',
        link: function (scope, element, attrs) {

            var el = angular.element("<div ng-include='templateUrl'></div>");
            $compile(el)(scope);
            element.replaceWith(el);
        },
        controller: ['$scope', function ($scope) {
            $scope.dataList = {};

            $scope.refreshDataList = function (url) {
                // Not shown in this example...
                ngDataListSvc.refreshGrid(url)
                    .then(function (data) {
                        $scope.dataList.data = data;
                    });
            }
        }]
    };
}]);

然后在我的页面控制器中,我可以简单地执行

app.controller('TestCtrl', ['$scope', function ($scope) {                   
    $scope.someClick = function () {
        $scope.refreshDataList('@(Url.Action("GetDataList"))');
    }
}]);