AngularJS Remove old $watchers when re-compiling d

2019-05-06 19:39发布

I have an AngularJS application that used to Build Pages dynamically (retrieve an XML from Server and by reading that XML building pages or forms) for an XML we have to build few pages all are related with each other and can be negative via 'Next' , 'Previous' buttons.

to implement that we have something like,

<div>
   <form name="myController.mainForm" novalidate>
      <div my-dynamic="myController.dynamicHtml"></div>
   </form>
</div>

herer myDynamic is directive, which deals with generated html and when we have to navigate to another page we generate new HTML for that page and assign it tomyController.dynamicHtml

and in that Directive I have something like this,

link: function postLink(scope, element, attrs) {
    scope.$watch(attrs.myDynamic, function (html) {
        element.html(html);
        $compile(element.contents())(scope);
    });
}

Now in each page I have number of input controls(or directives), and each have few bindings that that adds to number of watchers.

I have notice that if I negative navigate, to another page, watchers on previous pages not getting destroyed, until my-dynamic directive gets removed from scope.

What I need to do to make sure that watches on previous page gets destroyed when we again compile the HTML.

2条回答
不美不萌又怎样
2楼-- · 2019-05-06 20:02

Everytime the $compile service links something to a scope, it adds watchers. That is why directives such as ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes. They link to the child scope and destroy that scope when destroying the compiled DOM. Use scope.$new and scope.$destroy.

link: function postLink(scope, element, attrs) {
    var newScope;
    scope.$watch(attrs.myDynamic, function (html) {
        if (newScope) {
            newScope.$destroy();
        };
        element.empty();
        if (html) {
            element.html(html);
            newScope = scope.$new()
            $compile(element.contents())(newScope);
        };
    });
}

This creates and destroys a child scope on changes.

查看更多
闹够了就滚
3楼-- · 2019-05-06 20:06

You can unwatch anything by assigning a variable to the watch:

var dynamicWatcher = scope.$watch(attrs.myDynamic, function (html) {
    element.html(html);
    $compile(element.contents())(scope);

    dynamicWatcher(); // unwatch
});

See the documentation at the return type:

Returns function()
Returns a deregistration function for this listener.

查看更多
登录 后发表回答