在工厂中存储$ scope

时间:2015-06-09 19:51:31

标签: angularjs

我正在为我自己编写的Web应用程序添加功能。我觉得无法添加滑动功能。

我在某个地方看到“$ scope无法在工厂中访问”,但我设法在工厂中存储了由ng-repeat创建的所有范围。由于JavaScript通过值传递,我可能不会“存储范围”,但如果我在工厂内设置范围ng-class,我可以清楚地看到差异。我认为这是一个好主意,因为范围遍历是一种痛苦。我是否打击黄金,或者我是否在存储范围很大的数据时浪费速度和空间?

HTML

main.html中

<div ng-controller="someCtrlWhichWasDeclaredALongTimeAgo">
    .
    .
    . 
    <div class="items-container"
         ui-sortable="sortableOptions"
         ng-model="selectedSession.items">
        <div ng-repeat="item in selectedSession.items"
             ng-controller="itemEditorCtrl"
             ng-class="{'item-last':$last}">
            <div ng-if="item._value !== undefined"
                 class="item inline-comment">
                <span class="handle"></span>
            </div>
            <div ng-if="item._value === undefined"
                 class="item"
                 ng-include="'/views/item-editor.html'"></div>
            </div>
        </div>

        <div class="stopper"></div>
    </div>
</div>

项-editor.html

<div item-editor
     swipe-function="swipeMe"
     ng-swipe-left="swipeLeft(item)" 
     ng-swipe-right="swipeRight(item)">
     ...
</div>

这将使用我的魔法代码呈现一个列表。如果单击列表中的项目,它将扩展为全屏。您应该可以在那里滑动项目。

我认为我不得发布超过HTML来解释问题。我确实设法使用$ rootScope进行滑动。$ broadcast但是如果我的列表中有100个项目怎么办?随着越来越多的物品接收消息并处理它们,它会不会变慢?我宁愿在选择此会话时将所有范围加载到一个工厂中,然后在取消选择会话时将其删除。可能需要一些时间才能开始,但刷卡不需要5分钟。

3 个答案:

答案 0 :(得分:2)

你正在做的事情完全没问题。您可以随意在应用程序周围传递范围对象。请记住它们代表的内容。 $scope对象是您与视图的接口。大多数情况下,您的服务与视图几乎没有关系,理想情况下应该用于在控制器和指令之间共享数据。也就是说,有几个例子表明服务间接影响视图是完全合理的。例如,我们编写了一个spinner service,允许微调器指令在服务中注册自己。

spinner指令将spinnerService注入其中,调用spinnerService.register函数并传入其隔离范围,以便服务可以跟踪它并使用它来打开和关闭微调器。然后我们的开发人员可以在任何需要的地方注入服务,并在需要时隐藏/显示加载微调器或微调器组。

他们的意思是&#34; $ scope无法在工厂访问&#34;是你不能注入 $scope在工厂内。 $scope绑定到DOM元素(调用控制器或isolate指令的元素),因此将新的$scope注入工厂并没有多大意义,实际上是不可能的。您无法app.factory('myFactory', function ($scope) { ... });但您可以从控制器或指令调用您的工厂/服务,并将范围对象从那里传递到您在服务上提供的方法。

只要您知道自己在做什么,跟踪服务范围内没有任何问题。人们会告诉你,你不能将你的范围转移到服务中,因为它是一种反模式,但是他们会建议在你的指令/控制器中放置这样的东西,然后将它传递给服务:

var api = {
  hideSpinner: function () {
    $scope.show = false;
  },
  showSpinner: function () {
    $scope.show = true;
  }
};

当然,您并非直接$scope对象传递给服务,但如果参数是您的范围对象可能卡在内存中而从未收集垃圾,这个解决方案也没有帮助。您构建和传递的API对象将使用其JavaScript范围链,在内存中保留定义范围内的所有变量,包括控制器/指令的$scope。它必须,或者那些API方法不起作用。您的$scope 是该组件的一种API,可以这样使用它。

执行类似上述示例的更好的理由是,您的$scope对象可能包含您不需要/想要与服务共享的信息或功能。使用您希望向服务公开的内容制作一个小API对象非常有意义。然后,您的服务只能访问您希望它访问的内容,并且仍然可以影响控制器/指令$scope,但仅限于您传入的API对象概述的方式。

答案 1 :(得分:1)

请远离将$scope个对象存储在任何类型的全局商店中。这包括$ rootScope和Angular Services。

由于Angular中的服务是单例,如果任何服务正在跟踪$scope对象(在任何服务变量中),那么$scope可能永远不会释放,并且存在内存泄漏的可能性。

此外,scope的概念与视图紧密相关,不应在该上下文之外使用。

也许您可以围绕您的实施分享一些代码,以便我们建议更好的解决方案。

答案 2 :(得分:0)

  

“无法在工厂中访问$ scope”

几乎正确。您无法将$scope服务注入其他服务。没有什么可以阻止您创建存储数据的服务,并将$ scope作为数据。

这是一个不好的想法。服务用于在组件之间共享数据。 $scope用于与视图通信。把它想象成香蕉和烤面包机。两者都有目的,任何人都不会因为使用其中一个而对您造成错误,但使用服务存储$ scope就像在烤面包机里塞香蕉一样。

使用$scope的每个组件只应关注自己的范围 - 而不是其他组件(除非您知道自己在做什么,否则不应该使用它们除外)。

相反,将数据放入服务中,然后将服务的数据放入范围:

.controller('ExampleController', function($scope, myService) {
  $scope.names = myService.names;
});

更好的是,您可以考虑使用controllerAs syntax