【问题标题】:Make sure DOM changes are finished before transition确保 DOM 更改在过渡前完成
【发布时间】:2015-09-16 00:31:51
【问题描述】:

短版

当 ui-router 转换到新视图时(以某种我不完全理解的方式使用 ngAnimate),它会将 ng-leaveng-leave-active 类添加到当前视图。它还将ng-enterng-enter-active 类添加到下一个视图。问题是在下一个视图中的所有 DOM 更改完成之前开始转换,导致转换不稳定。所以我的问题是;是否可以防止添加 ng-enterng-enter-active 类,直到我决定添加它们(通过从控制器传输事件等)?

加长版

我正在开发一个使用 ui-router 和 ng-animate 进行转换的 AngularJS 应用程序。我遇到了一个小的性能问题,我真的很想解决这个问题以使应用程序运行更顺畅。

状态之间的转换似乎卡顿了,我发现这是可能,因为在转换过程中,Angular 正在执行 DOM 更改,同时发生转换。

如何确保在进行转换之前完成下一个视图中的 DOM 更改?我正在使用 ui-router 的解析功能以及防止在加载数据之前发生转换的承诺。

我创建了一个JSFiddle 来说明我的问题。单击链接进入 state2 时,resolve 行需要一段时间才能用数据解析(正如预期的那样)。但是,当转换发生时,DOM 似乎还没有准备好,因为转换可能非常滞后。这让我觉得当转换发生时 DOM 还没有准备好。

app.js

angular.module('myApp', ['ui.router', 'ngAnimate'])
.config(['$stateProvider',  
    function ($stateProvider) {
        $stateProvider
            .state('state1', {
                url: '',
                views: {
                    'main': {
                        templateUrl: "state1.html",
                        controller: function(){

                        }
                    }
                }
            })
            .state('state2', {
                url: '/state2',
                views: {
                    'main': {
                        templateUrl: "state2.html",
                        controller: function($scope, rows){
                            $scope.rows = rows;
                        },
                        resolve: {
                            rows: function($q){
                                var rows = [];
                                var deferred = $q.defer();

                                for (var i = 0; i < 10000; i++){
                                    rows.push({a: i, b: i/2, c: 3*i/2});
                                }

                                deferred.resolve(rows);

                                return deferred.promise;
                            }
                        }
                    }
                }
            });
    }])

模板

<div ui-view="main" class="main"></div>

<script type="text/ng-template" id="state1.html">
    <a ui-sref="state2">Go to state 2</a>
</script>

<script type="text/ng-template" id="state2.html">
    <a ui-sref="state1">Back to state 1</a>

    <table>
        <tr>
            <th>a</th>
            <th>b</th>
            <th>c</th>
        </tr>
        <tr ng-repeat="row in rows">
            <td>{{row.a}}</td>
            <td>{{row.b}}</td>
            <td>{{row.c}}</td>
        </tr>
    </table>
</script>

css

.main{
    transition: all 1s ease;
    position: absolute;
    width: 100%;
}

.main.ng-enter{
    transform: translateX(30%);
    opacity: 0;
}

.main.ng-enter.ng-enter-active{
    transform: translateX(0);
    opacity: 1;
}

.main.ng-leave{
    transform: translateX(0);
    opacity: 1;
}

.main.ng-leave.ng-leave-active{
    transform: translateX(-30%);
    opacity: 0;
}

【问题讨论】:

  • 嗨 Anton,您能否更具体地了解一下您的元素以及何时发生?也许一些代码会有所帮助!
  • 嗨@bobleujr!我已经用两个代码和一个 JSFiddle 的链接更新了我的问题!
  • 我已经用我的问题的较短版本再次更新了问题!
  • 我有几个解决方案,想看看你已经想出了什么。监听转换事件 + ng-if 就是其中之一。另一个是事件。

标签: angularjs angular-ui-router ng-animate


【解决方案1】:

问题是ng-repeat。它为每个元素创建一个监视,因此随着元素数量的增加,性能会降低。超过 2000-3000 个元素肯定会影响 ng-repeat 的性能。

如果您确实需要使用 ng-repeat 显示大量行,那么我建议您选择:
1. 分页
2.使用limitTo过滤器无限滚动。

可以参考这里:
https://stackoverflow.com/a/17350875/5052704

希望这会有所帮助!

【讨论】:

  • ng-repeat 和元素数量不是主要问题。我不希望它在 DOM 完成更改之前开始转换。内容的创建方式并不重要。我可以让我的控制器在 DOM 准备好时广播一个事件左右,但我需要 nganimate 在我说它应该这样做之前不添加 ng-enter-active 类
【解决方案2】:

This 是我在废弃 github 问题后得到的。我觉得通过使用 feat($animate) 可以通过暗示关闭回调来解决这个问题。你介意按照链接中的建议尝试吗?一旦我有一些时间,我会尝试用它来构建 plunker。

【讨论】:

  • 看起来可能是什么东西,得深入研究一下!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-06
  • 2017-09-21
  • 2016-09-12
相关资源
最近更新 更多