29

我第一次尝试 AngularJS 自定义指令。

我在使用(或理解......)指令的链接功能中的隔离范围时遇到问题。

这是我的应用程序这一部分的代码:

视图.html

...
<raw-data id="request-data" title="XML of the request" data="request">See the request</raw-data>
...

request是在 viewCtrl 范围内发布的变量,其中包含请求的 xml 字符串。

rawData.js

directives.directive('rawData', function() {

    return {
        restrict : 'E',
        templateUrl : 'partials/directives/raw-data.html',
        replace : true,
        transclude : true,
        scope : {
            id : '@',
            title : '@',
            data : '='
        },
        link : function($scope, $elem, $attr) {
            console.log($scope.data); //the data is correclty printed
            console.log($scope.id); //undefined
        }
    };
});

原始数据.html

<div>
    <!-- Button to trigger modal -->
    <a href="#{{id}}Modal" role="button" class="btn" data-toggle="modal" ng-transclude></a>

    <!-- Modal -->
    <div id="{{id}}Modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="{{id}}Modal" aria-hidden="true">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="myModalLabel">{{ title }}</h3>
        </div>
        <div class="modal-body">
            <textarea class="input-block-level" rows="10">{{ data }}</textarea>
        </div>
        <div class="modal-footer">
            <!-- <button class="btn" ng-click="toggleTagText('')">{{'cacher'}} l'image</button> -->
            <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Fermer</button>
        </div>
    </div>
</div>

我不明白为什么在模式弹出时会正确显示 ID,但是当我尝试console.log()它时,它的值是未定义的。

也许我对隔离范围值(=@)有误。

感谢您的阅读。:)

4

4 回答 4

36

绑定的隔离范围属性@不会立即在链接函数中可用。您需要使用$observe

$attr.$observe('id', function(value) {
   console.log(value);
});

您的模板可以正常工作,因为 Angular 会自动id为您更新隔离范围属性。当它更新时,您的模板也会自动更新。

如果您只是传递字符串,则可以简单地评估一次值而不是使用@绑定:

link: function($scope, $elem, $attr) {
    var id    = $attr.id;
    var title = $attr.title
    console.log(id, title);
}

但是,在您的情况下,由于您想使用模板中的属性,您应该使用@.

如果您没有使用模板,那么@当属性值包含{{}}s 时很有用 - 例如,title="{{myTitle}}". 那么使用的需要就$observe变得更加明显了:你的链接函数可能要在每次值myTitle变化时做一些事情。

于 2013-06-14T15:13:09.123 回答
10

这是故意的,并且与编译顺序以及“@”和“=”之间的区别有关。

此 Google Groups 讨论的一些摘录以及 Misko 的输入:

@ 和 = 做非常不同的事情。一个复制属性值(可能是内插的),另一个将属性值视为表达式。

@attrs 直到稍后才 $interpolated,因此它们在链接时不可用。如果你想在链接函数中对它们做一些事情,你要么需要手动 $interpolate

于 2013-06-14T15:14:16.417 回答
0

您可以在此处访问我创建的 JSFiddle: http: //jsfiddle.net/7t984sf9/5/

link: function($scope, $elem, $attr) {
    console.log($scope.onewayObject);
    $attr.$observe('onewayObject', function(value) {
         console.log(value);
    });
}

或者这里有一些更详细的解释:What is the difference between & vs @ and = in angularJS

于 2014-12-31T00:57:34.363 回答
0

好吧,上面的答案实际上都没有提到一个关键方面,即使使用'=',在我看来你也不能像下面这样直接访问链接函数内的范围,

scope: {
    data: '=',
},
link: function(scope, elem, attrs) {
    console.debug(scope.data); // undefined

但是您可以在内部函数中访问范围,

link: function(scope, elem, attrs) {
    scope.saveComment = function() {
        console.debug(scope.data);

所以在我看来,当 scope.data 可用时可能会有时间滞后。

于 2014-12-28T18:04:37.327 回答