如何保证 AngularJS 更新了 DOM?

Mr_Jing
  • 4.4k

我在页面上用 ng-repeat 循环输出了 list,通过点击按钮,我又向 list 中新添加了 10 个元素。这时候,列表的 height 应该变高了,我怎么能立刻获取到这个新的高度哩?

<!doctype html>
<html lang="en" data-ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        #box {
            width: 100px;
            height: 300px;
            overflow-y: scroll;
        }
    </style>
</head>
<body>

<div data-ng-controller="ScrollCtrl">
    <ul id="box">
        <li data-ng-repeat="item in list">{{item}}</li>
    </ul>

    <button type="button" data-ng-click="add()">Add</button>
</div>

<script src="jquery.min.js"></script>
<script src="angular.min.js"></script>
<script>
    angular.module('myApp', [])
            .controller('ScrollCtrl', function ($scope) {
                $scope.list = [3, 2, 1];


                $scope.boxScrollHeight = function () {
                    var box = angular.element('#box');
                    return box.get(0).scrollHeight;
                };


                $scope.add = function () {
                    console.log('before:', $scope.boxScrollHeight());

                    var last = $scope.list[0];
                    for (var i = 1; i <= 10; i++) {
                        $scope.list.unshift(last + i);
                    }

                    console.log('after:', $scope.boxScrollHeight());
                };
            });
</script>
</body>
</html>

点击按钮后,数据应该是立即改变了,但是数据改变到更新 DOM 还有一段时间。控制台输出的 before 和 after 是一样的。也就是获取 after 的高度时 DOM 还没有更新,如何才能获取到增加后的高度?

回复
阅读 3.9k
4 个回答

为什么一定要在数据更新完后就取数据?你完全可以先不管他,等你操作视图时在获取数据不就行了。

一般是$apply完成数据到视图的更新。
有时用$digest

$scope.$apply()是触发数据更新,利用 $scope.$watch() 去判断。

注意:不是直接监听数据,第一个参数设置为 function,那么这个 function 会执行多次,总有一次是 DOM 完成更新了执行的。
所以,可以在这个函数里面去做一些事情。

                $scope.$watch(function () {
                    console.log('before:', $scope.before);

                    console.log('after:', $scope.boxScrollHeight());
                    if ($scope.boxScrollHeight() != $scope.before) {
                        var box = angular.element('#box');
                        box.scrollTop($scope.boxScrollHeight() / 2);
                    }
                });

提前记录了一个值:$scope.before,如果后面获取的值和 $scope.before 不相同,说明 DOM 已经更新完毕了,然后就可以做一些操作了。

理解$watch ,$apply 和 $digest --- 理解数据绑定过程

使用$timeout.延迟获取.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏