AngularJS - 关于性能和范围的一些初学者问题

时间:2015-04-09 10:59:36

标签: javascript angularjs

我最近继承了第三方开发人员编写的角度模块。我之前从未使用角度,并且被要求做出一些相当基本的改变,但是我正在努力解决几个问题(我保证在这个问题的末尾有一个问题)。

本质上,模块只是一个多选问卷,带有一系列按钮,您可以单击一个选择答案,然后单击前进/后退按钮以在问题之间移动。

当模块硬编码为使用5个按钮时,按钮的位置在控制器中设置如下:

// scope here is the scope for the main controller
$scope.answerOptions = [
    { pos: 70 },
    { pos: 215 },
    { pos: 360 },
    { pos: 505 },
    { pos: 650 }
];

pos只是左偏移,垂直位置是固定的。这是在模板上实现的,如下所示:

<div class="circle" ng-repeat="o in answerOptions"
    option-pos="{{o.pos}}"
    ng-hide="sectionEnd"
    ng-class="selectedOptionStyle($parent.selectedAnswer - 1 == $index)"
    ng-click="selectAnswer($index)">
</div>

然后指令optionPos

.directive('optionPos', function(){
  return function(scope, elm, attrs) {
    attrs.$observe('optionPos', function(x){
      elm.css('left', x - 60 + 'px');
    })
  }
})

我被要求使用任意数量的按钮并在x和y中定位,并允许自定义的答案(此时它只是将点击按钮的数组索引发送回服务器)。我认为这将是一个简单的改变,并且不可否认,如果我实现相同的系统,使用插值设置x和y,然后只需将y添加到optionPos指令就足够了。但是我对这种方法有几个问题:

  • 对于按钮上的属性数量,它不能很好地扩展。例如除了x和y还有一些我想从answerOption对象分配给按钮的其他数据(例如发送到服务器的答案,以及未来可能的其他东西),我不想必须将每一个分配为DOM元素的单独属性。
  • 我担心attrs.$observe是不必要的资源密集型,因为一旦模块加载,值将永远不会改变,$ observe(可能是?)将监视添加到该属性。类似地,使用插值来设置DOM元素上的坐标。
  • 在一些不确定的方式中感觉不对,就像有更好的方法可以做到这一点,我只是没有向Google提出正确的问题。

在大量阅读Angular的文档和教程后,我尝试做的是这样的:

// this would no longer be hard coded into the controller
// but once it is retrieved, this is what is set in the scope
// scope is still the main controller scope
$scope.answerOptions = [
    { Answer: 1, pos: { X: 180, Y: 120} },
    { Answer: 2, pos: { X: 360, Y: 120} },
    { Answer: 3, pos: { X: 540, Y: 120} }
];

模板:

<div class="circle" ng-repeat="o in answerOptions"
    answer-option="o"
    option-button
    ng-hide="sectionEnd"
    ng-class="selectedOptionStyle($parent.selectedAnswer - 1 == $index)"
    ng-click="selectAnswer(o.Answer)">
</div>

指令:

.directive('optionButton', function(){
     return {
         restrict: 'A',
         scope: {
             answerOption: '='
         },
         link: function(scope, elm, attrs) {
             elm.css('left', scope.answerOption.pos.X - 60 + 'px');
             elm.css('top', scope.answerOption.pos.Y - 60 + 'px');
         }
     }

上面的解决方案的问题是我的指令是创建一个独立的范围,所以所有其他带有函数调用的指令,例如ng-hide现在都被打破了,我不想要重新构建整个模块,实质上是一个非常简单的变化

所以,正如我漫长的漫无目的所承诺的那样 - 问题:

对于任何超过24小时角度经验的人,我是否会采取这种错误方式?我遇到的问题让我觉得这就像代码味道一样,但我不确定它是否因为原始开发人员以难以维护/扩展的方式编写模块,或者我正在服用完全错误的做法。我遇到的问题似乎源于这样一个事实,即基本上整个应用程序逻辑被设置为主控制器范围内的各种功能。它需要大约800行JS来设置该控制器的范围,许多函数定义了大量不同的东西。这是应该构建角度应用程序的方式,范围内的大多数逻辑,然后直接从模板调用它,例如, ng-hide="sectionEnd"

1 个答案:

答案 0 :(得分:1)

一个怪物控制器不是好习惯。页面上的每个控制器都应该是聚焦的,并且最多应该有5个方法(指南)。通过集中控制器,您可以管理应用程序获取数据的方式。

一旦你有控制器来检索你的应用程序数据,你应该利用指令将功能封装到可重用的指令中。

此外,如果属性及其插值永远不会改变,$ observe将不会产生大量成本。

我建议遵循以下准则:

  1. 实施服务以检索应用程序数据
  2. 控制器应调用服务以检索应用程序数据并将其附加到范围。
  3. 指令应该有助于保持控制器的精简,并通过将复杂或共享逻辑保留在可重用指令中来提高可维护性。