我正在学习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'}];
}
});
在此方案中修改范围的最佳方法是什么?有没有办法使用只能由服务和指令封装的范围,但是其他人不能访问它?
答案 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"))');
}
}]);