Tôi muốn tạo động các thành phần góc sử dụng javascript và sau đó biên dịch góc bằng cách sử dụng $compile
với phạm vi mới được tạo. Sau đó, khi tôi không còn sử dụng cho thành phần đó, tôi muốn phá hủy thành phần và phạm vi mới.
Mọi thứ hoạt động như mong đợi, ngoại trừ thực tế là mặc dù tôi đang phá hủy phạm vi mới, tất cả bộ nhớ mà nó sử dụng sẽ không bao giờ được phát hành.
Dưới đây là một phần của một phiên bản đơn giản hóa của mã mà:
app.controller("mainCtrl", ["$scope", "$compile", function($scope, $compile) {
var childScope;
//call this every time the button is clicked
this.createDirective = function() {
//dynamically create a new instance of the custom directive
var customDirective = document.createElement("custom-directive");
//if another child scope exists, destroy it
if (childScope) {
childScope.$destroy();
childScope = undefined;
}
//create a new child scope
childScope = $scope.$new();
//compile the custom directive
$compile(customDirective)(childScope);
};
}]);
Full dụ làm việc của mã này là here
Tất cả các mã này không, là tạo ra một thành phần mới mỗi khi nút được click , nhưng trước tiên hãy hủy mọi thành phần đã tồn tại. Lưu ý rằng tôi không thực sự thêm thành phần được biên dịch vào trang, vì tôi nhận thấy rằng sự rò rỉ vẫn ở đó bất kể tôi có sử dụng nó hay không.
Sử dụng công cụ phát triển của Chrome (Profiles -> Ghi Allocation Timeline -> Start) Tôi thấy sử dụng bộ nhớ sau sau khi nhấp vào nút một vài lần:
Rõ ràng là bất kỳ bộ nhớ bị chiếm đóng bởi customDirective không bao giờ thực sự được phát hành, mặc dù chức năng $destroy
của phạm vi đang được gọi.
Tôi đã sử dụng thành công $compile
trước đây mà không tạo phạm vi mới, nhưng có vẻ như tôi thiếu một số thứ trong trường hợp này. Tôi có nên làm điều gì đó khác để đảm bảo rằng không có tham chiếu đến phạm vi mới?
Sửa
Dựa trên câu trả lời dưới đây bởi JoelCDoyle, đây là việc sửa chữa (tôi thêm một chức năng trên phá hủy đến phạm vi tôi tạo):
app.controller("mainCtrl", ["$scope", "$compile", function($scope, $compile) {
var childScope;
//call this every time the button is clicked
this.createDirective = function() {
//dynamically create a new instance of the custom directive
var customDirective = document.createElement("custom-directive");
//if another child scope exists, destroy it
if (childScope) {
childScope.$destroy();
childScope = undefined;
}
//create a new child scope
childScope = $scope.$new();
//compile the custom directive
var compiledElement = $compile(customDirective)(childScope);
//FIX: remove the angular element
childScope.$on("$destroy", function() {
compiledElement.remove();
});
};
}]);
Điều này thực sự trông rất hứa hẹn vì nó sửa chữa ví dụ fiddle. Tôi sẽ áp dụng nó vào ứng dụng của tôi và xem nó có hoạt động ở đó không – kapoiosKapou
Có! điều này cũng làm việc cho ứng dụng phức tạp hơn của tôi ..! Mặc dù .. Tôi vẫn không hiểu chính xác * tại sao * tác phẩm này hoạt động. Tôi không thêm nó vào DOM, vậy tại sao nó cần phải được loại bỏ? Ngoài ra, ngay cả khi tôi đã thêm phần tử đã biên dịch vào DOM và sau đó xóa nó, bộ nhớ vẫn bị rò rỉ. Có phải $ compile cũng đang thêm địa điểm này vào một nơi khác không? giống như một bộ nhớ cache ..? – kapoiosKapou