简体   繁体   English

AngularJS:视图完全加载后即可进行DOM操作

[英]AngularJS: DOM manipulation once view is fully loaded

Apologies for the long post - I hope it doesn't put too many people off. 很长的道歉-我希望它不会让太多人失望。 What I have is working, but I'm just not sure if it's the "correct" way of doing things, so I'm just looking for some advice. 我所拥有的正在工作,但是我不确定这是否是“正确”的工作方式,所以我只是在寻找一些建议。

I have a page where I'm using the window size to calculate where to position a dynamic number of elements. 我有一个页面,我在其中使用窗口大小来计算动态元素数量的位置。 These elements are spaced out according to how big the window is, and then I'm using the Canvas element to draw lines connecting each element to a central element. 这些元素根据窗口的大小间隔开,然后使用Canvas元素绘制将每个元素连接到中心元素的线。

The problem I have is knowing when all elements have been created and are now ready for resizing and positioning. 我遇到的问题是知道何时创建了所有元素,现在可以调整大小和定位了。

My HTML is something like this: 我的HTML是这样的:

    <div class="panel">
        <div class="panel_content">
            <div class="input_mapping" ng-repeat="input in inputs" mapping-resize>
                {{input.name}}
            </div>
        </div>
    </div>
    <div class="panel">
        <div class="panel_content">
            <div class="central_mapping">
                {{mapping.name}}
            </div>
        </div>
    </div>
    <div class="panel">
        <div class="panel_content">
            <div class="output_mapping" ng-repeat="output in outputs" mapping-resize>
                {{output.name}}
            </div>
        </div>
    </div>

I'm using the directive, mapping-resize, to resize everything but this runs on each ng-repeat. 我正在使用指令mapping-resize调整所有内容的大小,但这在每个ng-repeat上运行。 Really, I only want to run it once, once all the child elements are created but if I put the directive on the parent div (panel_content), it isn't aware of the child elements at the point the directive runs and so doesn't reposition them. 确实,一旦所有子元素都被创建,我只想运行一次,但是如果我将指令放在父div(panel_content)上,它在指令运行的那一刻就不会意识到子元素,所以不会。重新放置它们。

My directive is currently this: 我的指令目前是这样的:

app.directive('mappingResize', ['$timeout', function($timeout) {
    return function(scope, elem, attrs) {

        if(scope.$last) {
            $timeout(function() {
                positionElements();
            });
        }
    }
}]);

positionElements() is, as it suggests, where all my code is for positioning elements once they've been created. 就像它建议的那样,positionElements()是我所有的代码,用于在元素创建后定位它们。 It's working fine, although it could probably be done in a more "angular way" (it's just a standard JS function which is reliant on full-blown jQuery). 它可以很好地工作,尽管它可以用一种“更角度的方式”完成(这只是一个标准的JS函数,它依赖于成熟的jQuery)。

In the directive, I'm using the $last property so I only call positionElements() if it's the last element in the ng-repeat, as I need to know about all of them in order to position them correctly. 在指令中,我使用的是$ last属性,因此如果它是ng-repeat中的最后一个元素,我只会调用positionElements(),因为我需要了解所有这些元素才能正确放置它们。 I'm also using $timeout so the code is queued to run after the page is rendered. 我也在使用$ timeout,因此代码在页面呈现后排队运行。

My question is, is this the best I can do? 我的问题是,这是我能做的最好的吗?

At the moment, I'm calling positionElements() twice - once for the input mappings ng-repeat, and once for the output mappings. 目前,我两次调用positionElements()-一次用于输入映射ng-repeat,一次用于输出映射。 Really, I just need to call it once (and only once) when all mapping elements have been created. 实际上,在创建所有映射元素后,我只需要调用一次(并且只能调用一次)。 It also doesn't feel very nice to be using $timeout and $last - it feels like there would be some event that tells me that the view has been created, but everything I've found has been a dead end. 使用$ timeout和$ last感觉也不太好-感觉好像会有一些事件告诉我视图已创建,但是我发现的一切都是死胡同。

Anyway, suggestions or advice on the above would be most appreciated. 无论如何,对以上建议或意见将不胜感激。

Use $timeout and move your directive at the end of your page: 使用$ timeout并将指令移至页面末尾:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.model = { items: [1,2,3,4,5] };
});

app.directive('directive', function () {
  return {
    link : function (scope, elem, attrs) {
      console.log(attrs.index);
    }
  }
});

app.directive('lastDirective', function ($timeout) {
  return {
    link : function (scope, elem, attrs) {
      $timeout(function () {
        // position elements here
        console.log(attrs.index);
      });
    }
  }
});

HTML: HTML:

  <body ng-controller="MainCtrl">
    <div ng-repeat="item in model.items" directive index="1"></div>
    <div ng-repeat="item in model.items" directive index="2"></div>
    <div last-directive index="3"></div>
  </body>

open console to see directive execution order 打开控制台以查看指令执行顺序

http://plnkr.co/edit/Y1KIGAa7hDjY9STlmPm2?p=preview http://plnkr.co/edit/Y1KIGAa7hDjY9STlmPm2?p=preview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM