简体   繁体   中英

What to use instead of angular scope functions?

I don't like angular scope functions - they don't have a clear contract. They take their parameters somewhere in the scope and put their results somewhere to scope instead of explicitly take parameters as function parameters and return the result. Take this example ( plunkr ):

HTML

<html ng-app="exampleApp">

  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <script src="myctrl.js"></script>
  </head>

  <body ng-controller="MyCtrl">
    Here is my params:
    <input type="number" ng-model="first"> + <input type="number" ng-model="second">
    <button ng-click="sum()">Sum it!</button>
    <p>{{result}}</p>
  </body>

</html>

JS

//myctrl.js
var app = angular.module('exampleApp', []);

app.controller('MyCtrl', function($scope) {
  $scope.sum = function() {
    $scope.result = $scope.first + $scope.second;
  }
});

As soon as the function becomes bigger than 10 lines, it can be tricky to understand what should be its main result. Also I don't understand how to document it with jsdoc. Is there some best practice for better functions in angular?

PS The example here is a bit synthetic, most of the time my function would ask the angular service something and transform the result for display.

PPS Many people suggest controller as syntax, but I think it doesn't solve the problem completely, the function still can't have return value and all that it does is hidden in side-effects.

You can use controller as instead of $scope .

<body ng-controller="MyCtrl as ctrl">

  <body ng-controller="MyCtrl as ctrl">
    Here is my params:
    <input type="number" ng-model="ctrl.first"> + <input type="number" ng-model="ctrl.second">
    <button ng-click="ctrl.sum()">Sum it!</button>
    <p>{{ctrl.result}}</p>
  </body>

IN JS

//myctrl.js

var app = angular.module('exampleApp', []);

app.controller('MyCtrl', function() {
 var vm = this;
  vm.sum = function() {
   vm.result = vm.first + vm.second;
  }
});

Yes, attaching everything to the scope object can be troublesome in that dependencies become unclear and the implementation becomes longer. The alternative is to publish the controller as object into the scope and have the view bind to it directly using the controller as syntax:

function MyCtrl() {
    this.first = 0;
    this.second = 0;
    this.result = 0;
}

MyCtrl.prototype.sum = function () {
    this.result = this.first + this.second;
}

angular.module('example', []).controller('MyCtrl', MyCtrl);
<body ng-controller="MyCtrl as ctrl">
    Here is my params:
    <input type="number" ng-model="ctrl.first"> + <input type="number" ng-model="ctrl.second">
    <button ng-click="ctrl.sum()">Sum it!</button>
    <p>{{ ctrl.result }}</p>
</body>

See https://docs.angularjs.org/api/ng/directive/ngController#example .

According to the " Angular Style guide " published in the GitHub, You should be using the the controllerAs syntax over the classic controller with $scope syntax.

Reason #1 : Controllers are constructed, "newed" up, and provide a single new instance, and the controllerAs syntax is closer to that of a JavaScript constructor than the classic $scope syntax.

Reason #2 : It promotes the use of binding to a "dotted" object in the View (eg customer.name instead of name), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting".

Reason #3 : Helps avoid using $parent calls in Views with nested controllers.

<!-- avoid -->
<div ng-controller="CustomerController">
    {{ name }}
</div>


<!-- recommended -->
<div ng-controller="CustomerController as customer">
    {{ customer.name }}
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM