Angular的$ scope中额外抽象层的优点/缺点

时间:2014-01-22 14:27:36

标签: javascript angularjs angularjs-scope

我稍微修改了以下网址(http://docs.angularjs.org/cookbook/helloworld)中的示例,如下所示,将name值放在attrs对象属性中:

<!doctype html>
<html ng-app>
  <head>
    <script src="http://code.angularjs.org/1.2.9/angular.min.js"></script>
    <script>
      function HelloCntl($scope) {
        $scope.attrs = {
            name : 'World'
        }
      }
    </script>
  </head>
  <body>
    <div ng-controller="HelloCntl">
      Your name: <input type="text" ng-model="attrs.name"/>
      <hr/>
      Hello {{attrs.name || "World"}}!
    </div>
  </body>
</html>

我可以看到的一个好处是 HTML 源代码可以搜索/attrs\.\w+/(例如),如果需要在视图中轻松找到所有这些属性而不是控制器(例如,搜索name可能与表单元素名称冲突)。同样在控制器中我只能想象前端所需的分区属性可能会使自己更好地组织。

是否有其他人使用这种抽象级别。它的使用是否有任何可能的具体进一步的好处?最重要的是,可能存在任何特定的缺点。

2 个答案:

答案 0 :(得分:2)

建议您始终在ngModel中使用一个点,以避免Angular's Guide to Understanding Scopes中讨论的原型继承的潜在问题:

  

通过遵循以下内容,可以轻松避免使用原语这个问题   always have a '.' in your ng-models的“最佳实践” - 观察3   分钟值得。 Misko演示了原始绑定问题   NG-开关。

原型继承和原语

javascripts的继承方法以不同的方式阅读和写入原始行为。在读取时,如果当前范围上不存在原语,则它会尝试在任何父范围上找到它。但是,如果您写入当前范围上不存在的原语,它会立即在该范围上创建一个原语。

你可以看到这可能导致in this fiddle有3个范围的问题 - 一个父母和两个孩子是兄弟姐妹。首先在“父”中键入内容,您将看到两个子项都已更新。然后在其中一个孩子中键入不同的内容。现在。只有那个孩子被更新,因为写入导致孩子创建它自己的变量副本。如果您现在再次更新父级,则只有另一个子级将跟踪它。如果你在兄弟姐妹的孩子里输入一些内容,那么这三个范围现在都有自己的副本。

这显然会导致很多问题。

原型继承和对象

尝试使用this fiddle进行相同的实验,其中每个ngModel使用对象的属性而不是基元。现在读写一致

当你写入一个对象的属性时,它就像读取一样(和写入基元的方式相反)。如果您正在写入的对象在当前作用域中不存在,则会查找它的父链以尝试查找该对象。如果找到具有该名称的名称,则它会写入该找到的对象上的属性。

因此,虽然在原始示例中我们从1变量开始,然后在写入子项后最终得到3个变量副本 - 当我们使用对象时,我们只在一个对象上拥有一个属性。

由于我们几乎总是(或许只是总是)想要这种一致行为,因此建议仅使用对象属性,而不是ngModel中的基元,或者更常见的是,“始终在您的点中使用点ngModel

答案 1 :(得分:2)

我也是这样做的。我还将所有动作函数(按钮单击等)放入$ scope.actions对象中。因为我使用socket.io我将这些回调放入$ scope.events对象中,它通常使我的控制器保持良好和有条理,并且能够轻松地找到我需要的功能,如果我需要进行任何编辑。

app.controller('Ctrl',['$scope', function ($scope) {
    $scope.data = {
        //contains data like arrays,strings,numbers etc
    };

    $scope.actions = {
        //contains callback functions for actions like button clicks, select boxes changed etc
    };

    $scope.events = {
        //contains callback functions for socket.io events
    }
]);

然后像我的模板一样,我可以像

一样
<input ng-click="actions.doSomething()">

我也为服务做了部分工作。我使用私有和公共数据对象

app.factory('$sysMsgService',['$rootScope',function($rootScope){
    //data that the outside scope does not need to see.
    var privateData = {};
    var service = {
        data:{
            //contains the public data the service needs to keep track of
        },
        //service functions defined after this
    };
    return service;
}]);