慢反应,按一下按钮在1000项NgRepeat列表 [英] Slow reaction to button click in NgRepeat list of 1000 items

查看:263
本文介绍了慢反应,按一下按钮在1000项NgRepeat列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有超过1000项,我在展示角1.3使用NgRepeat列表。该列表填充的按钮。我注意到上的click事件诠释他列出一旦它生长在大小显著延迟。当列表只有5-10项的点击是即时的。当列表是1000还有就是点击按钮实际上是处理前约2-5秒的延迟。

I have a list of 1000+ items which I display using NgRepeat in Angular 1.3. The list populates with buttons. I have noticed significant delay on the click event int he list once it grows in size. When the list is only 5-10 items the clicks are instant. When the list is 1000 there is about 2-5 second delay before the button clicks are actually processed.

现在我不能告诉如果这是一个浏览器的问题,但我怀疑它有太多的听众做某处被使用,导致浏览器来检查他们。

Now I cannot tell if this is a browser issue, but I suspect it has to do with too many listeners being used somewhere, causing the browser to check for them.

下面是情况下,code的样品有一个罪魁祸首躲在有:

Here is sample of code in case there is a culprit hiding in there:

<div id="side" class="animated" style="min-height: 250px;" 
    data-ng-class="{'fadeInRight':documentDone}" data-ng-style="settings.listCss">
    <div class="col-md-12 text-center" data-ng-style="settings.listCss"><h4>{{label}}</h4> {{inSide}} </div>
    <div data-ng-repeat="doc in ::documents track by $index" id="{{ ::doc.id }}" 
        class="document ng-hide" data-ng-show="doc.show"
        data-ng-init="docSettings = (settingslist[doc.companyid] || settings)" data-ng-style="::docSettings.listCss">
        <div class="col-md-12" data-ng-style="docSettings.listCss">
            <h4>
                <span>{{ ::$index + 1 }}</span>
                <span class="title-in-clusters">
                    {{ ::doc.title }}
                    <button type="button" 
                        class="btn btn-primary btn-xs" 
                        data-ng-click="viewJob(doc, docSettings)" 
                        data-ng-style="docSettings.buttonCss">
                        <strong>VIEW</strong>
                    </button>
                    <a href="{{ ::doc.joburl }}" class="apply" target="_blank">
                        <button type="button" class="btn btn-primary btn-xs" data-ng-click="apply(doc.jobid, doc.companyid)" 
                            data-ng-style="docSettings.buttonCss">
                            <strong>APPLY</strong>
                        </button>
                    </a>
                </span>
            </h4>
        </div>
        <div class="col-md-12" data-ng-style="docSettings.listCss">
            <span class=""><strong>ID: </strong>{{ ::doc.jobid }}</span>
            <img data-ng-if="docSettings.heading.logourl && docSettings.heading.logourl != ''" 
                data-ng-src="{{docSettings.heading.logourl}}" class="side-logo inline-block" id="">
        </div>
        <div class="col-md-12" data-ng-style="docSettings.listCss">
            <strong>Location: </strong><span class="">{{ ::doc.location }}</span>
        </div>                  
        <div class="col-md-12" data-ng-style="docSettings.listCss">
            <strong>Updated Date: </strong><span class="">{{ ::doc.updateddate }}</span>
        </div>
        <div class="col-md-12" data-ng-style="docSettings.listCss">
            <hr data-ng-style="docSettings.listCss">
        </div>
    </div>
</div>

有没有什么进攻有关在调用的时候,按钮pressed其他功能。

There is nothing offensive about the other functions that are called when the button is pressed.

var modalInstance;
$scope.viewJob = function(modalDoc, docSettings) {
    $scope.modalDoc = modalDoc;
    $scope.docSettings = docSettings;
    //the trusAsHtml takes string creates an object, so this will in essence convert string to object
    //make sure you check if it is a string since it could be called multiple times by user (close and reopen same modal)
    if (modalDoc.overview && typeof modalDoc.overview === 'string') {
        $scope.modalDoc.overview = $sce.trustAsHtml(modalDoc.overview);
    }
    if (modalDoc.qualifications && typeof modalDoc.qualifications === 'string') {
        $scope.modalDoc.qualifications = $sce.trustAsHtml(modalDoc.qualifications);
    }
    if (modalDoc.responsibilities && typeof modalDoc.responsibilities === 'string') {
        $scope.modalDoc.responsibilities = $sce.trustAsHtml(modalDoc.responsibilities);
    }

    modalInstance = $modal.open({
      templateUrl: 'app/modal/job_preview.html',
      //templateUrl: 'myModalContent.html',
      scope: $scope
    });
  };

我要优化这个code,因此它可以切断高达1500的列表,但我不能为我的生活找到罪魁祸首。

I want to optimize this code so it can sever a list of up to 1500, but I cannot for the life of me find the culprit.

我也将采取任何解决方案来降低负载来代替。就像现在,我想我可能会限制DOM元素的数量,以10左右,有角旋转什么被视为用户滚动它是否会带来更好的UX。

I will also take any solutions to reduce the load instead. Like for now I am thinking I may limit the number of DOM elements to 10 to so, and have angular rotate what is being viewed as user scrolls if it will result in better UX.

更新:

很多东西都试过,一次绑定从使用到的延缓一些哪些ENAT,但需要大量的数学要估算项目都可见等。

Many things have been tried, from use of bind-once to more convoluted solutions that retard some of the watchers Which are enat but require a lot of Math to estimate which items are visible etc.

我终于决定在一个解决方案,这是最容易做的。我只是做项目的清单祝显示和鼠标上的向上或向下滚动我编辑列表

I finally decided on one solution that was easiest to do: I made a list of only items I wish shown and on mouse scroll up or down I edit the list.

解决方案的第一部分是采用两个指令:

First part of the solution is use of two directives:

.directive('ngMouseWheelUp', function() {
    return function($scope, $element, $attrs) {
        $element.bind("DOMMouseScroll mousewheel onmousewheel",     
        function(event) {
                    // cross-browser wheel delta
                    var event = window.event || event; // old IE support
                    var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));

                    if(delta > 0) {
                        $scope.$apply(function(){
                            $scope.$eval($attrs.ngMouseWheelUp);
                        });

                        // for IE
                        event.returnValue = false;
                        // for Chrome and Firefox
                        if(event.preventDefault) {
                            event.preventDefault();                        
                        }

                    }
        });
    };
})
.directive('ngMouseWheelDown', function() {

    return function($scope, $element, $attrs) {

        $element.bind("DOMMouseScroll mousewheel onmousewheel", function(event) {

                    // cross-browser wheel delta
                    var event = window.event || event; // old IE support
                    var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));

                    //console.log(event);

                    if(delta < 0) {
                        $scope.$apply(function(){
                            $scope.$eval($attrs.ngMouseWheelDown);
                        });

                        // for IE
                        event.returnValue = false;
                        // for Chrome and Firefox
                        if(event.preventDefault)  {
                            event.preventDefault();
                        }

                    }
        });
    };
})

这两个使我在上右侧的列表以禁用滚动。然后,我会创造从routeScope文件两个额外的阵列。每当文档进行了更新,就可以产生一个列表(这是由右侧图形的用户界面发出事件的事件侦听器),该过滤器将只返回了显示属性设置为true阵列成员:

These two enable me to disable scrolling in the list on the right side. Then I would create two additional arrays from the documents in routeScope. First list would be generated whenever the documents were updated (which was an event listener for event emitted by the UI of the right hand side graph), this filter would only return array members that had the show property set to true:

var showFilter = function(object) {
    return object.show;
}

这将是我看到的项目数组。从这个数组我创建中显示的项目的另一个数组。我定义为7最大尺寸恒定,所以最有7所示的物品。当然我设置父容器溢出到无以禁用滚动条。 (这样用户就知道他可以滚动这个领域我可能会增加滚动图形版本)

This would be my array of visible items. From this array I created another Array of shown items. I defined a constant for max size of 7, so at most there are 7 items shown. And of course I set overflow of the parent container to none to disable scrollbar. (I may add a scroll graphic so the user knows he can scroll this field later)

然后我说下面的指令到一边DIV:
    数据-NG-鼠标滚轮向上=listUp()的数据-NG-鼠标滚轮向下=listDown()
和控制器内部,我定义listUp和listDown工作过常量的指数,最大尺寸要弄清楚,我要补充的前面或显示清单背面从列表中可见的元素。

Then I added the following directives to the side div: data-ng-mouse-wheel-up="listUp()" data-ng-mouse-wheel-down="listDown()" And inside the controller I defined listUp and listDown to work off an index and the max size constant to figure out which elements from the visible list I should add to the front or the back of the shown list.

/**
 * Simulate scrolling up of list by removing bottom element and adding to top
 */ 
$scope.listUp = function() {
    $rootScope.shownDocuments.unshift(getPrev());
    $rootScope.shownDocuments.pop();
}
/**
 * Simulate scrolling down of list by removing top element and adding to bottom
 */
$scope.listDown = function() {
    $rootScope.shownDocuments.push(getNext());
    $rootScope.shownDocuments.shift();
}
/**
 * return next item in visibleDocuments array
 */
var getNext = function() {
    $rootScope.topIndex++;
    if ($rootScope.topIndex > $rootScope.visibleDocuments.length) {
        $rootScope.topIndex -= $rootScope.visibleDocuments.length;
    }
    return ($rootScope.visibleDocuments[($rootScope.topIndex+max_shown_size)%$rootScope.visibleDocuments.length]);
}
/**
 * Return previous item in visibleDocuments array
 */
var getPrev = function() {
    $rootScope.topIndex--;
    if ($rootScope.topIndex < 0) {
        $rootScope.topIndex += $rootScope.visibleDocuments.length;
    }
    return ($rootScope.visibleDocuments[$scope.topIndex]);
}

使用rootScope的VS范围,主要是因为情态动词会导致一些不良的行为,如果他们被解雇不当

Use of rootScope vs scope is mostly because modals would cause some undesirable behaviors if they were dismissed improperly.

最后的视图复位功能:

/**
 * Resets the list of documents in the visibleList (IE which are visible to client)
 */
var updateVisibleDocuments = function() {
    $rootScope.topIndex = 0;
    $rootScope.visibleDocuments = $rootScope.documents.filter(showFilter);
    //clear view
    $rootScope.shownDocuments = [];
    $rootScope.topIndex = 0;
    for (var i = 0; i < max_shown_size; i++) {
        $rootScope.shownDocuments.push(getNext());
    }
    $rootScope.topIndex = 0;
}

此解决方案的作品真的很好,因为我只呈现7个项目即使我的列表中有10万项。这限制了观察家的极大数量

This solution works really well because I only render 7 items even if my list has 100k items. This limits number of watchers tremendously.

推荐答案

您可能想尝试分页,以减少对事物的角度量和浏览器需要在任何时间来处理在屏幕上。

You may want to try paginating to reduce the amount of things angular and the browser need to deal with on screen at any one time.

这篇关于慢反应,按一下按钮在1000项NgRepeat列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆