Angularjs 如何删除由使用$compile动态添加和删除的模板创建的监视程序?
我们有这个指令,允许开发人员使用$compile指定他们自己的模板和数据,这些模板和数据将用于绑定到该模板的范围。模板可能有角度表达式,这将创建观察者 当模板和作用域表示的元素内容从DOM树中删除时,如何删除使用它创建的观察者 这证明了即使从树中删除了它所代表的DOM,观察者也会留下来 第一次单击compile按钮将编译角度模板并将其附加到DOM树。第二次单击该按钮时,它将清空添加上一个模板的元素,并添加新编译的模板 index.htmlAngularjs 如何删除由使用$compile动态添加和删除的模板创建的监视程序?,angularjs,Angularjs,我们有这个指令,允许开发人员使用$compile指定他们自己的模板和数据,这些模板和数据将用于绑定到该模板的范围。模板可能有角度表达式,这将创建观察者 当模板和作用域表示的元素内容从DOM树中删除时,如何删除使用它创建的观察者 这证明了即使从树中删除了它所代表的DOM,观察者也会留下来 第一次单击compile按钮将编译角度模板并将其附加到DOM树。第二次单击该按钮时,它将清空添加上一个模板的元素,并添加新编译的模板 index.html <!DOCTYPE html> <ht
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="jquery@1.7.2" data-semver="1.7.2" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script data-require="angular.js@1.2.6" data-semver="1.2.6" src="https://code.angularjs.org/1.2.6/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="smart-table-debug.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="controller">
<h1>Compile Demo</h1>
HTML to compile<br/>
<textarea id="html" ng-model="html"></textarea>
<br/>
Result<br/>
<div id="result"></div>
<br/>
<input type="button" value="compile" ng-click="compile()" />
<br/>
Compile time: {{ compileTime }}<br/>
Watchers count: {{ watchersCount }}<br/>
Digest count: {{ digestCount }} <br/>
Total time taken: {{ totalTime }} milliseconds <br/>
</body>
</html>
编译演示
要编译的HTML
结果
编译时间:{{compileTime}}
观察者计数:{{watchersCount}}
摘要计数:{{digestCount}}
所用总时间:{{totalTime}}毫秒
script.js
function getAllScopes( rootScope, allScopes ) {
if( !allScopes ) {
allScopes = [];
}
allScopes.push( rootScope );
for( var scope = rootScope.$$childHead; scope; scope = scope.$$nextSibling ) {
getAllScopes( scope, allScopes );
}
return allScopes;
}
angular.module( "app", [] )
.controller( "controller", ["$scope", "$compile", "$rootScope", "$timeout", function($scope, $compile, $rootScope, $timeout ){
var e = angular.element;
$scope.html = "<div>{{watchersCount}}</div>"
$scope.watchersCount = 0;
$scope.digestCount = 0;
$scope.compileClickStart = performance.now();
$scope.totalTime = 0;
/* because we didn't gave watch expression as 1st parameter but a functionn,
* the function will be called at every end of digest cycle.
* https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest
*/
$rootScope.$watch(function() {
$scope.digestCount += 1;
$scope.totalTime = performance.now() - $scope.compileClickStart;
});
$scope.compile = function(){
$scope.digestCount = 0;
$scope.compileClickStart = performance.now();
var insertTarget = e('#result');
var targetScope = $scope.$new();
insertTarget.empty();
t0 = performance.now();
var expandedContent = $compile($scope.html)(targetScope);
t1 = performance.now();
$scope.compileTime = (t1 - t0) + " milliseconds.";
insertTarget.append( expandedContent );
$timeout( function() {
var allScopes = getAllScopes($rootScope);
var allWatchers = [];
for( var i = 0; i < allScopes.length; i++ ) {
var scope = allScopes[i];
if( scope.$$watchers) {
//allWatchers = allWatchers.concat( scope.$$watchers );
for( var j = 0; j < scope.$$watchers.length; j++ ) {
allWatchers.push({
"scope" : scope,
"watcher" : scope.$$watchers[j]
});
}
}
}
console.log( allScopes );
$scope.watchersCount = allWatchers.length;
});
};
}]);
函数getAllScopes(根范围,所有范围){
如果(!所有范围){
所有范围=[];
}
allScopes.push(rootScope);
对于(var scope=rootScope.$$childHead;scope;scope=scope.$$nextSibling){
getAllScopes(范围,所有范围);
}
返回所有作用域;
}
角度模块(“应用程序”,[])
.controller(“控制器”、[“$scope”、“$compile”、“$rootScope”、“$timeout”、函数($scope、$compile、$rootScope、$timeout){
var e=角元素;
$scope.html=“{{watchersCount}}”
$scope.watchersCount=0;
$scope.digestCount=0;
$scope.compileClickStart=performance.now();
$scope.totalTime=0;
/*因为我们没有将watch表达式作为第一个参数,而是一个函数n,
*该函数将在摘要周期的每个末尾调用。
* https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest
*/
$rootScope.$watch(函数(){
$scope.digestCount+=1;
$scope.totalTime=performance.now()-$scope.compileClickStart;
});
$scope.compile=函数(){
$scope.digestCount=0;
$scope.compileClickStart=performance.now();
var insertTarget=e(“#结果”);
var targetScope=$scope.$new();
insertTarget.empty();
t0=性能。现在();
var expandedContent=$compile($scope.html)(targetScope);
t1=性能。现在();
$scope.compileTime=(t1-t0)+“毫秒”;
insertTarget.append(expandedContent);
$timeout(函数(){
var allScopes=getAllScopes($rootScope);
var allWatchers=[];
对于(var i=0;ivar expandedContent;
$scope.compile = function(){
// ...
var insertTarget = e('#result');
var targetScope = $scope.$new();
if (expandedContent) {
expandedContent.scope().$destroy();
}
insertTarget.empty();
expandedContent = $compile($scope.html)(targetScope);
insertTarget.append( expandedContent );
// ...
}
如果您已经在指令中使用了此功能,那么在其链接功能中使用此功能时会更干净。侦听从DOM中删除元素的时间,并相应地清理作用域
link: function (scope, element, attrs) {
element.on("$destroy", function () {
scope.$destroy();
})
}
不是真的。我做了一些实验并计算了观察者的数量,这并没有减少观察者的数量。稍后我会放一些演示链接来证明它。用链接更新了我的问题,以证明即使它所代表的DOM从树中删除,观察者仍然存在。expandedContent.scope().$destroy();他对嵌套指令非常挑剔。thnx如果调试数据被禁用,并且
element.scope()
不可用,那么最好的方法是什么?