jquery - 指令中缺少子元素

标签 jquery angularjs angularjs-directive

我定义了一个指令:


$(function () {
    angular.module(['myApp']).directive('rootSlider', function () {
        return {
            restrict: 'E',
            template: '<ul><li ng-repeat="item in items"><img ng-src="{{item.url}}" /></li></ul>',           
            scope: {
                items: '='
            },
            replace: true,
            compile: function ($templateElement, $templateAttributes) {
                return function ($scope, $element, $attrs) {

                    var $scope.items.length //expect 2, get 2
                    var numChildren $element.children().length //expect 2, get 0
                };
            }
        };
    });
});

Although the $scope.items property has 2 items, and in the final rendered DOM there are two <li> elements, in the link function $element does not yet have children.

At what point in the angular lifecycle can I get the completely rendered element (my intention is to use a jQuery slider plugin here).

The markup is

<root-slider items="ModelPropertyWithTwoItems"></root-slider>

更新:

我能够通过 $watchCollection 和 $evalAsync 的组合使其正常工作。

$(function () {
    angular.module(['myApp']).directive('rootSlider', ['$timeout', function ($timeout) {
        return {
            restrict: 'E',
            template: '<ul class="bxslider"><li ng-repeat="item in items"><img ng-src="{{item.url}}" /></li></ul>',
            scope: {
                items: '='
            },
            compile: function ($templateElement, $templateAttributes) {
                return function ($scope, $element, $attrs) {
                    $scope.$watchCollection('items', function (newCollection, oldCollection) {
                        if ($scope.slider) {
                            $scope.$evalAsync(function () {
                                $scope.slider.reloadSlider();
                            });
                        }
                        else {

                            $scope.$evalAsync(function () {
                                $scope.slider = $element.find('.bxslider').bxSlider();
                            });
                        }

                    });

                };
            }
        };
    } ]);
});

Watch 集合在指令初始化时触发一次(因为它是一个集合,因此您无法比较 newValue 和 oldValue,因此我最终将 slider 对象添加到为指令实例创建的 $scope 中。

我使用 $evalAsync 来推迟 jQuery 代码的执行,该代码(到目前为止)被证明可以避免所有浏览器上的闪烁(它似乎在 $timeout(function(){}, 0 之前运行)。

上面的解决方案可能可以通过仅返回一个链接函数(而不是一个编译函数,结果证明这是不必要的)来简化。

最佳答案

在 Angular 中等待 DOM 完成渲染的常见方法是使用 $timeout。这是 explanation各种选项和 here's another look at this .

所以这应该可以为您解决这个问题。在您的指令中包含 $timeout:

angular.module(['myApp']).directive('rootSlider', function ($timeout) {

然后包裹你的

$timeout(function() {
     var numChildren $element.children().length;
},0);

已经有request for a more official feature supporting this这是 Angular 自己的 Misko Hevery在关闭问题之前的评论:

So that is a very complex question. The issue is that with data-binding there is no clear start/end to the update cycle, it is continues. I am sure that is not the answer you are looking for, but angular is not like other frameworks, and so it lives by different rules.

How would you imagine this would work? What kind of and when should you receive these notifications.

到目前为止,似乎没有人对 3emad 接近尾声时发布的这个问题做出回应:

I'm just curious about $timeout down side

我认为这种方法令人鼓舞,因为尚未有人发布其缺点。

关于jquery - 指令中缺少子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20671928/

相关文章:

javascript - 我可以使用 Angular 变量作为音频标签的来源吗?

javascript - jQuery setInterval 不起作用

javascript - 附加到特定元素

javascript - JQuery自动完成如何在自动完成文本输入中写标签?

javascript - 指令需要在元素呈现后更新数据

javascript - 将函数表达式存储在 angularjs 指令的链接函数中并通过 ng-click 使用它

jquery - "Undefined index: data"

javascript - 当服务器宕机时,不会返回错误

Angularjs 在代码隐藏中翻译

jquery - 使用 Angular.js 时如何使用 jQuery 插件