简体   繁体   中英

What happens behind the scenes when binding to a function in AngularJS

Can anyone explain what happens behind the scenes when you bind to a function in AngularJS? What kind of watch does it create? I have a feeling it would create two watches (in my example below) one for each property that makes up the return value. However I'm certainly not sure about this but it feels like something we shouldn't do.

eg

<div ng-show="vm.someFunc()">

JS

vm.someFunc = function() {  
    return vm.property1 || vm.property2;
}

If you created the angular scope method "vm.someFunc()", this will continuously get polled. You can verify this by setting a breakpoint in this method, it will continuously keep getting hit. If you check the task manager and show the browser running your website, the memory keeps going up and won't stop.

In my opinion, scope functions should only be used when using event triggers: click event, change event, keypressed are some of the examples.

Showing or hiding aren't events, so this is why it gets polled like that.To fix and provide the same functionality, turn this into a scope variable.
change the html tag from:

<div ng-show="vm.someFunc()">

to

<div ng-show="vm.someFunc">

And in your controller:

$scope.KeyPressed = false;
$scope.Tags = '';

then create a watch event on what you want to watch for:

//initialize showtag when page loads
$scope.vm.someFunc = $scope.KeyPressed && $scope.Tags !== '';

//watch for any new changes on keypressed
$scope.$watch('KeyPressed', function (newValue, oldValue) {
     if (newValue && $scope.Tags !== '') {
         $scope.vm.someFunc= true;
     } else {
         $scope.vm.someFunc= false;
     }
}

//watch for any new changes on keypressed
$scope.$watch('Tags', function (newValue, oldValue) {
     if (newValue !== "" && $scope.KeyPressed) {
         $scope.vm.someFunc= true;
     } else {
         $scope.vm.someFunc= false;
     }
}

Or you can change to a "watchCollection" instead of having multiple watches like:

$watchCollection('[KeyPressed, Tags]', function (newValue) { }

newValue[0] is the value of KeyPressed, and newValue[1] is the value of Tags

Or to go along with the accepted answer and minimize the amount of watches:

$scope.TruthyVal= function () {
    return $scope.KeyPressed && $scope.Tags !== '';
};

$scope.$watch('TruthyVal', function (newValue, oldValue) {
     if (newValue) {
         $scope.vm.someFunc= true;
     } else {
         $scope.vm.someFunc= false;
     }
}

In fact angular does not care what you write in html - function, variable or whatever. It takes expression as string, parse it and calculate its value each digest cycle. So, {{1 + 2}} and {{sum(1, 2)}} and {{1 | sum:2}} {{1 | sum:2}} are actually doing same job at more or less same speed.

All three ways are legit and do not create memory leaks.

The reason why it is always not recommended to use functions in ng-show is that lot of functions are time consuming, so your digest becomes very slow. And even if your functions are fast, you are not guaranteed that they wont grow up in future.

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