Как я могу отфильтровать список компонентов AngularJS, которые перерисовываются дорого? - PullRequest
0 голосов
/ 13 июня 2019

Возьмите следующий код AngularJS:

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.js"></script>
    <script src="main.js"></script>
</head>
<body ng-app="app" ng-controller="RootController as vm">
    <input type="text" ng-model="vm.search" /> <br />
    <component ng-repeat="i in vm.indices | filter:vm.search" index="i"></component>
</body>
</html>

main.js

const app = angular.module("app", []);

class RootController
{
    constructor()
    {
        this.indices = [...Array(1000).keys()];
    }
}

class ComponentController
{
    constructor()
    {
    }

    getMessage()
    {
        var startTime = Date.now();
        while (Date.now() < startTime + 1) {}
        return this.index;
    }
}

app.controller("RootController", RootController);
app.component("component",
    {
        controller: ComponentController,
        controllerAs: "vm",
        template: `
            {{vm.getMessage()}}
        `,
        bindings: {
            index: "<"
        }
    }
);

Имеет следующие свойства:

  1. У нас есть список значений JS (массив "индексы").
  2. Мы ng-repeat над этим списком, чтобы создать список компонентов.Каждое значение в нем передается компоненту в качестве параметра.
  3. Рендеринг компонента зависит от этого индекса, но как только он будет выполнен, его уже никогда не придется делать снова (это детерминировано с учетом индекса).
  4. Индексы будут отфильтрованы, но никогда не будут изменены.
  5. Рендеринг компонента стоит дорого.

Кажется, что когда я что-то набираю для фильтрации списка, AngularJS долженперерисовывать каждый компонент каждый раз, и это медленноТеоретически он должен просто скрывать и показывать компоненты, вызывая getMessage() один раз для каждого компонента при загрузке страницы.Как я могу получить такое поведение?

Я попробовал однократное связывание ::, которое ускоряет его при вводе поискового запроса, но когда я стираю запрос, он снова замедляется, так как я полагаю, что он все еще имеетвызвать getMessage(), чтобы заново нарисовать компоненты, от которых он избавился.

1 Ответ

0 голосов
/ 13 июня 2019

Вместо вызова функции из шаблона инициализируйте модель в компонентном контроллере:

class ComponentController
{
    constructor()
    {
    }

    $onInit() {
         this.message = this.index;
    }

    /*   
    getMessage()
    {
        var startTime = Date.now();
        while (Date.now() < startTime + 1) {}
        return this.index;
    }
    */
}

Затем просто используйте модель в шаблоне:

app.component("component",
    {
        controller: ComponentController,
        controllerAs: "vm",
        template: `
            ̶{̶{̶v̶m̶.̶g̶e̶t̶M̶e̶s̶s̶a̶g̶e̶(̶)̶}̶}̶
            {{vm.message}}
        `,
        bindings: {
            index: "<"
        }
    }
);

Также производительность может быть улучшена с помощью предложения track by:

<body ng-app="app" ng-controller="RootController as vm">
    <input type="text" ng-model="vm.search" /> <br />
    <component ng-repeat="i in vm.indices | filter:vm.search track by i"
               index="i">
    </component>
</body>

Чтобы свести к минимуму создание элементов DOM, ngRepeat использует функцию, чтобы «отслеживать» все элементы в коллекции и их соответствующие DOMэлементы.Например, если элемент добавлен в коллекцию, ngRepeat будет знать, что все другие элементы уже имеют элементы DOM, и не будет повторно отображать их.

Для получения дополнительной информации см.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...