This fiddle应该让事情变得更清楚,但本质上我是在其指令中分配元素的一些属性(如它的 id)参数:
myApp.directive('myDiv', function () {
return {
restrict: 'E',
replace: true,
scope: {
'elementId': '@',
'displayName': '@',
},
transclude: true,
template: '<div class="my-div" id="{{elementId}}">{{displayName}}<div ng-transclude></div></div>'
}
})
问题是,如果我在启动时立即执行操作,例如初始化其他指令,则这些值(例如 elementId)尚未插值。
换句话说,如果我获得对 myDiv 元素的引用并打印其 id,则在启动时立即打印“{{elementId}}”。但是,如果我等待很短的时间(例如一秒钟),则会打印作为值传递给 element-id 属性的值(正如我所期望的那样)。
如果您在查看 Fiddle 时打开控制台,您就会看到这一点。
我在这里做错了什么?我怎样才能避免这种情况(除了启动时出现很多非常难看的超时)?
最佳答案
你有几处不正确。这是一个新的 fiddle ,您可以在其中看到“首先”日志显示正确的值:http://jsfiddle.net/0mq2xv8m/
1) 您应该将内部元素包含在第二个模板中。您已将 transclude 设置为 true,因此它将替换您的节点。这也确保了在第一个指令准备好之前第二个指令不会绑定(bind)。 IE。由于它与外部指令一起位于 DOM 中,因此它的实例化可能与包装指令不同步。
template: '<div class="my-div" id="elementId">{{displayName}}<div my-field></div></div>'
2) 使用 id="elementId"
而不是 id="{{elementId}}"
通过引用而不是值传递
3) 通常,在父级上获取属性是不好的做法,最好通过 2 路绑定(bind)传递它。这在我使用过的任何面向显示列表的编程中都是如此。
良好实践:
您应该对任何“init”步骤使用 Controller 或链接函数。在指令链接其所有属性/范围之前,这些不会运行。按照您的方式,它是在 $scope 创建期间的评估步骤中执行的(还没有范围)。链接函数和 Controller 等待 $scope 变得可用。可以使用 Controller 代替链接函数(我认为它更清晰且更易于单元测试)。
angular.module('App').controller('someController',[], function() {
var controller = {
init:function(){
console.log(elementId);
}
}
controller.init();
return controller;
});
myApp.directive('myDiv', function () {
return {
restrict: 'E',
replace: true,
controller:'someController',
scope: {
'elementId': '@',
'displayName': '@',
},
transclude: true,
template: '<div class="my-div" id="{{elementId}}">{{displayName}}<div ng-transclude></div></div>'
}
关于angularjs - 当插入指令属性时,如何避免启动时的竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28908794/