質問

I'm writing an angular directive that has a function called init() that needs to run when the page loads, and any time two variables change. I started out with this:

link: function(scope, elem, attrs){
    init();
    //Refresh the view when the the type or typeId changes
    scope.$watch("[type,typeId]", function(){init(scope)}, true);
},

But I noticed that init() was actually getting called twice. After I took the first init() out it obviously would only run once, but I'm just curious, is this expected behavior?

I thought watch functions only execute when something changes. Is it because they are technically "changing" (being initialized after link?) or is it just the natural behavior of $watch to immediately execute the function?

役に立ちましたか?

解決

$watch listeners are called when they are registered. If you don't want to execute the code inside of your listener function when you are initializing the watcher, then you can do something like this:

scope.$watch("[type,typeId]", function(oldValue, newValue) {
    if (oldValue === newValue) return;

    // This code will only be hit when oldValue is different from newValue
    init(scope)
}, true);

他のヒント

appending to the accepted answer.. This even seems to be the "official" solution.

After a watcher is registered with the scope, the listener fn is called asynchronously (via $evalAsync) to initialize the watcher. In rare cases, this is undesirable because the listener is called when the result of watchExpression didn't change. To detect this scenario within the listener fn, you can compare the newVal and oldVal. If these two values are identical (===) then the listener was called due to initialization.

http://docs.angularjs.org/api/ng.$rootScope.Scope#methods_$watch

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top