$ digest完成后如何执行代码?

时间:2013-12-20 21:13:07

标签: angularjs angularjs-directive angularjs-ng-repeat

我有一个可排序的列表,它由我的Angular Controller中的数据填充。此列表还包含一个额外的元素,其中包含一些也可以拖动的控件

我想要做的是确保在运行$digest周期后额外的元素保持不变,并且我只针对该案例制定了指令。

App.directive('ngIgnore', ['$timeout',function($timeout){
  return {
    link: function(scope, element){
        scope.$watch(function(){
            // Keep track of the original position of the element...
            var el = element[0];
            var siblings = Array.prototype.slice.call(el.parentNode.children);
            var parent   = el.parentNode;
            var index    = siblings.indexOf(el);

            $timeout(function(){
                // After the digest is complete, place it to it's previous position if it exists
                // Otherwise angular places it to it's original position
                var item;
                if(index in parent.children)
                    item = parent.children[index];

                if(!!item){
                    parent.insertBefore(el, item);
                }
            });    
        });

    }
  }    
}]);

它有效,但不是我想要的......正如你在example改组中看到的那样,列表不会移动被忽略的元素,但问题是$watch函数得到了自$timeout触发另一个$digest周期后无限执行...我尝试用$timeout更改setTimeout但没有运气......

在$ digest执行后,是否有任何Angulary方法可以立即运行代码?或者我的整个逻辑是错误的吗?

2 个答案:

答案 0 :(得分:3)

另一个(强烈推荐的)解决方案是停止思考DOM操作。

开始编写AngularJS代码的开发人员的常见问题是由于某些事件而倾向于进行DOM操作。它在jQuery中很常见:

$('#someid').click(function() { this.toggleClass('clicked') })

在AngularJS中,您应该设计View以可视化您的Model状态(应该在$ scope中)。所以

<div ng-click="clicked = !clicked" ng-class="{clicked: clicked}">I was clicked</div>

在设计组件时应该应用相同的逻辑。在HTML代码中,您应该放置所有可视逻辑 - 使用ng-show / ng-ifng-switch隐藏一些元素。使用ng-class等添加/删除课程。因此,您可以定义所有可能的模型状态

然后,只需更改模型状态,您的视图就会自动更新,反映出当前的模型状态。

重复元素也是如此:您可以在某些集合上重复,然后根据存在的元素定义它的外观。请记住,在ng-repeat中,每个元素都有自己的子元素(因此大部分是独立的),所以你可以定义一些每个元素的操作。

另见这个好答案:"Thinking in AngularJS" if I have a jQuery background?

答案 1 :(得分:1)

您可以尝试使用Scope.evalAsync Scope.evalAsync

  

它将在安排评估的功能之后执行   (最好在DOM渲染之前)。