为什么我的指令的链接函数永远不会被调用? [英] Why does the link function of my directive never get called?

查看:28
本文介绍了为什么我的指令的链接函数永远不会被调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个指令:

 hpDsat.directive('ngElementReady', [function() {返回 {限制:A",链接:函数($scope,$element,$attributes){//把手表放在这里.console.log(" @#%*%$ 是什么???");$scope.$eval($attributes.ngElementReady);}};}]);

我从未看到 console.log 的输出.我正在声明一个这样的元素:

<div data-ng-element-ready="console.log(' ------------------------------- 编译!')" data-ng-if="analysis.type" data-ng-show="showBasicHtml" data-ng-include="analysis.type+'Content.html'"></div>

是的,我在声明 div 元素所在的控制器之前声明了指令.元素出现,ngShow 和 ngInclude 工作,加载模板中的任何内容也工作正常(更多指令、控制器、{{表达式}} 等).

如果我用编译函数执行它,编译函数确实工作,但仍然不是链接函数:

 hpDsat.directive('ngElementReady', [function() {返回 {限制:A",编译:函数($元素,$属性){console.log("我确实看到了.");//这有效!!返回函数($scope){//把手表放在这里.console.log("但不是这个.为什么???");//不工作!!$scope.$eval($attributes.ngElementReady);};}};}]);

编译函数的console.log工作正常,但返回的链接函数仍然没有被执行.

知道为什么链接函数可能不会被触发吗?

解决方案

错误可能在其他地方.我在 jsfiddle 中尝试过,第一个版本有效.

eval()

无论如何,您可能对 $scope.$eval() 的作用有误解:

$scope.$eval() 根据范围评估 angularjs 代码.JavaScript 的 eval() 函数在 angularjs 中运行任意 js 代码是 $window.eval().更多关于这里:Angular.js:$eval 是如何工作的,为什么它与普通的 eval 不同?

我测试了与控制器隔离的指令:

<div data-ng-element-ready="console.log('COMPILED!')"></div>

和指令:

app.directive('ngElementReady', ['$window', function($window) {返回 {限制:A",链接:函数($scope,$element,$attributes){console.log("到达链接 fn", $attributes);$window.eval($attributes.ngElementReady);}};}]);

我确实得到了到达链接 fn"的值,并且 $attributes 是正确的:

到达链接 fn Object { $$element={...}, $attr={...},ngElementReady="console.log('COMPILED!')", 更多...}

并且 $window.eval() 返回 COMPILED!

此处带有控制器.

在任何情况下,使用 eval() 来执行编写在属性中的代码看起来很危险.任何人都可以修改 DOM 以在那里运行代码.至少确保它不会影响任何其他用户或服务器端.

用 ng-if 重现问题

在第一条评论后我尝试将 ng-if 表达式计算为 false here这次它不显示消息.这可能是因为为了评估 ng-if,你必须首先编译指令.否则,它只是 anuglarjs 不知道的代码.但是,因为它是从 DOM 中移除的,所以它永远不会到达链接函数.

AngularJS 函数的执行顺序

一般来说,执行的顺序是这样的(Josh David米勒解释说:

<div指令2><!-- ... -->

现在 AngularJS 将通过按特定顺序运行指令函数来创建指令:

directive1:编译指令2:编译指令 1:控制器指令 1:预链接指令2:控制器指令2:预链接指令2:后链接指令 1:后链接

I have this directive:

    hpDsat.directive('ngElementReady', [function() {
        return {
            restrict: "A",
            link: function($scope, $element, $attributes) {
                // put watches here.
                console.log(" WHAT THE @#%*%$??? ");
                $scope.$eval($attributes.ngElementReady);
            }
        };
    }]);

I never see the output of the console.log. I'm declaring an element like this:

<div data-ng-element-ready="console.log(' ------------------------------- COMPILED! ')" data-ng-if="analysis.type" data-ng-show="showBasicHtml" data-ng-include="analysis.type+'Content.html'"></div>

Yes, I am declaring the directive before I declare the controller under which the div element exists. The element appears, ngShow and ngInclude works, and anything in the loaded template works just fine too (more directives, controllers, {{expressions}}, etc).

If I execute it with a compile function, the compile function does work, but still not the link function:

    hpDsat.directive('ngElementReady', [function() {
        return {
            restrict: "A",
            compile: function($element, $attributes) {
                console.log("This I do see."); // THIS WORKS!!
                return function($scope) {
                    // put watches here.
                    console.log("But not this. Why???"); // DOESN'T WORK!!
                    $scope.$eval($attributes.ngElementReady);
                };
            }
        };
    }]);

The console.log of the compile function works fine, but the returned link function still never gets executed.

Any idea why the link function might not get fired?

解决方案

The error might be somewhere else. I tried it in a jsfiddle and the first version works.

eval()

In any case, you might have a missunderstanding about what $scope.$eval() does:

$scope.$eval() evaluates angularjs code against a scope. JavaScript's eval() function to run arbitrary js code in angularjs is $window.eval(). More about this here: Angular.js: How does $eval work and why is it different from vanilla eval?

I tested the directive isolated from the controller:

<div data-ng-element-ready="console.log('COMPILED!')"></div>

and the directive:

app.directive('ngElementReady', ['$window', function($window) {
return {
    restrict: "A",
    link: function($scope, $element, $attributes) {
        console.log("Reached the link fn", $attributes);
        $window.eval($attributes.ngElementReady);
    }
};
}]);

I do get the value "reached the link fn" and $attributes is correct:

Reached the link fn Object { $$element={...}, $attr={...},  
ngElementReady="console.log('COMPILED!')", more...}

And $window.eval() returns COMPILED!

and here with a controller.

in any case, using eval() to execute code written in an attribute looks dangerous. Anybody can modify the DOM to run code there. At least make sure that it won't affect any other users or server-side.

Reproducing the problem with ng-if

Edited after first comment: I tried making the ng-if expression evaluate to false here This time it doesn't show the message. This probably happens because in order to evaluate ng-if, yuo must compile first the directive. otherwise, it's just code that anuglarjs isn't aware of. However, because it is removed from the DOM, it never reaches the link function.

Execution order of AngularJS functions

In general, the order of execution goes like this (Josh David Miller explains it:

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

Now AngularJS will create the directives by running directive functions in a certain order:

directive1: compile
  directive2: compile
directive1: controller
directive1: pre-link
  directive2: controller
  directive2: pre-link
  directive2: post-link
directive1: post-link

这篇关于为什么我的指令的链接函数永远不会被调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆