Javascript AngularJS编译代码“保留”;“在后面”;
我注意到对我来说似乎是一个bug,但可能更多的是我在AngularJS中误用了Javascript AngularJS编译代码“保留”;“在后面”;,javascript,angularjs,angularjs-compile,Javascript,Angularjs,Angularjs Compile,我注意到对我来说似乎是一个bug,但可能更多的是我在AngularJS中误用了$compile服务:我有一个名为“dynamic”的指令,它编译AngularJS代码并将其显示为div。在这种情况下,我编译的代码包含ng控制器,这些控制器正在侦听事件。问题在于,显然控制器在更换后并没有“死亡”,因为应该消失的控制器仍然会对事件(如$routeChangeSuccess或任何其他事件)做出反应。 这里有一个工作说明了这个问题。 让我们看看我的问题的示例代码: 我正在使用的指令: app.direc
$compile
服务:我有一个名为“dynamic”的指令,它编译AngularJS代码并将其显示为div。在这种情况下,我编译的代码包含ng控制器
,这些控制器正在侦听事件。问题在于,显然控制器在更换后并没有“死亡”,因为应该消失的控制器仍然会对事件(如$routeChangeSuccess
或任何其他事件)做出反应。
这里有一个工作说明了这个问题。
让我们看看我的问题的示例代码:
我正在使用的指令:
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, element, attrs) {
scope.$watch(attrs.dynamic, function(html) {
element.html(html);
$compile(element.contents())(scope);
});
}
};
});
主控制器,然后是我包含的控制器:
app.controller('TestCtrl', function($scope) {
$scope.dynamicContent = "Default content";
$scope.firstButton = function() {
$scope.dynamicContent = "<div ng-controller='FirstCtrl'>The div from first button</div>";
}
$scope.secondButton = function() {
$scope.dynamicContent = "<div ng-controller='SecondCtrl'>The div from second button</div>";
}
$scope.checkButton = function() {
$scope.$broadcast('checkEvent');
}
});
app.controller('FirstCtrl', function($scope) {
$scope.$on('checkEvent', function() {
alert(1);
});
});
app.controller('SecondCtrl', function($scope) {
$scope.$on('checkEvent', function() {
alert(2);
});
});
app.controller('TestCtrl',函数($scope){
$scope.dynamicContent=“默认内容”;
$scope.firstButton=函数(){
$scope.dynamicContent=“从第一个按钮开始的div”;
}
$scope.secondButton=函数(){
$scope.dynamicContent=“第二个按钮的div”;
}
$scope.checkButton=函数(){
$scope.$broadcast('checkEvent');
}
});
app.controller('FirstCtrl',函数($scope){
$scope.$on('checkEvent',function()){
警报(1);
});
});
应用程序控制器('SecondCtrl',函数($scope){
$scope.$on('checkEvent',function()){
警报(2);
});
});
现在,如果我调用firstButton()
然后调用secondButton()
然后调用checkButton()
,而不是只接收警报(2)
,我会收到两个警报。如果我点击按钮1/2/1/2/1/2/2/1/2,它将显示与我点击的按钮一样多的警报
我做错了什么
谢谢你,希尔纽斯,你的关系真好。首先,我将告诉您可能希望做什么,因为我不知道您对$compile服务的意图。然后,我将解释为什么这个实例不需要$compile服务,因为您可以有效地复制include 您可能希望做什么: 使用指令(特别是在尝试“$compile”动态内容时)的关键是确保您知道在何处传递什么范围。对于angularjs中内置的大多数指令,angular自动处理创建(via)和销毁(via)。由于您没有显式地“$destroy”,因此不会删除这些作用域。另一个问题是,您直接将“dynamic”指令附加到当前作用域,而没有在指令中创建子作用域或隔离作用域(通过$new):
app.directive('dynamic',function($compile){
返回{
限制:“A”,
链接:函数(范围、元素、属性){
var curScope=null,
curEle=null;
函数removeOld(){
if(光标){
光标。$destroy();
游标范围=空;
curEle.remove();
curEle=null;
}
}
作用域.$watch(attrs.dynamic,函数(html){
removeOld();
curScope=scope.$new();//创建子作用域(而不是隔离)
//可能应该在这里进行一些适当的转义,请参见$sce服务
curEle=angular.element(html);
如果(!curEle.length){
curEle=angular.element(“”+html+“”);
}
$compile(curEle)(光标);
元素。附加(刮匙);
});
}
};
});
您可能应该做的是:
对于像这样的一些小模板,您可能应该考虑将它们放入$TimePraceCHIVER(如下面的SUPKR所示的PUT)所以对于模板的任何请求都会自动加载它。你还必须考虑一些其他的事情,比如“HTML是否正确地被消毒了?”或者“我希望我的内容能正确地被动画化吗?”这些东西是用NG自动处理的,包括它几乎像你想复制的一样。
app.run(函数($templateCache){
$templateCache.put(“btn_default.html”,“默认内容”);
$templateCache.put(“btn_one.html”,“第一个按钮的div”);
$templateCache.put(“btn_two.html”,“第二个按钮的div”);
})
现在,您需要做的就是像这样使用预构建的:
第一个按钮
第二个按钮
检查事件
希望这有助于更好地理解。您的
动态
指令似乎做了ng include
所做的事情……除了ng include
(我的假设)可能使用了$scope。$destroy()要清除由加载的动态模板创建的作用域,我不能使用ng include,因为我要显示的是post请求的结果。在更改动态变量之前,我是否应该在正确的作用域中手动使用$scope.$destroy?是的,我会朝这个方向走。诚然,我一直依赖于控制器的角度处理/对我来说是作用域,所以我不知道这种方法会有多成功。也许看看创建/销毁作用域时会有什么帮助。我在发布您的意图后意识到,$templateCache并不真正适用,但它可能会在将来帮助其他人。非常感谢,真的很有帮助。第二部分也有帮助,但是cache被自动清除?(以避免内存泄漏)。此外,您的第一个plunkr与第二个plunkr相同,您可能希望更正此错误,以供以后的读者很高兴听到,链接对我来说是不同的,不确定那里发生了什么。您应该能够使用和使用$templateCache.remove('btn_default.html')例如,也不要忘记在这里标记一个最佳答案,所以:)。我还有一个问题:如果我没有使用控制器,而只是使用指令和{{}在我编译的代码中,它是自动垃圾收集还是手动销毁?我不确定你所说的{{}是什么意思,但是如果
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var curScope = null,
curEle = null;
function removeOld(){
if( curScope ){
curScope.$destroy();
curScope = null;
curEle.remove();
curEle = null;
}
}
scope.$watch(attrs.dynamic, function(html) {
removeOld();
curScope = scope.$new(); //creates child scope (not isolate)
//probably should do some proper escaping here see $sce service
curEle = angular.element( html );
if( !curEle.length ){
curEle = angular.element('<span>'+html+'</span>');
}
$compile( curEle )(curScope);
element.append( curEle );
});
}
};
});
app.run(function( $templateCache ){
$templateCache.put("btn_default.html", "Default content");
$templateCache.put("btn_one.html", "<div ng-controller='FirstCtrl'>The div from first button</div>");
$templateCache.put("btn_two.html", "<div ng-controller='SecondCtrl'>The div from second button</div>");
})
<div ng-controller="TestCtrl">
<div class="btn btn-default" ng-click="firstButton()">First button</div>
<div class="btn btn-default" ng-click="secondButton()">Second button</div>
<div class="btn btn-default" ng-click="checkButton()">Check events</div>
<div ng-include="dynamicContent"></div>
</div>