angular监听dom渲染完成,判断ng-repeat循环完成


风晓
风晓 2024-01-01 19:45:27 52228 赞同 0 反对 0
分类: 资源
如果只是感知静态的dom用ready,onload都可以,但项目用的angular,ng-repeat什么时候循环完,或者说angular自身的生命周期中dom渲染完成怎么知道

二、网上流传的解决方案

1.data-ng-init---无效

大概意思是,给你需要监听的dom,比如body添加一个data-ng-init属性,绑定你需要在body加载完成后执行的方法。

<div data-ng-init = "load()"></div>

$scope.load = function () {
    //dosomething
};

我查了下资料,在stackoverflow中找到了相关介绍,data-ng-init本质是ng-init,只是在对于H5之前,ng写法会报错,为了解决这个错误而添加data前缀达到兼容的写法,所以本质还是ng-init。

在HTML5开始之后,像Visual Studio这样的代码编辑器突出显示'ng-',这是无效的。但实际上它是有效的,所以有一种方法可以让代码编辑器通过在前面加上'data-ng- *'来理解AngularJS的属性是有效的。

因此,当在任何HTML5代码编辑器中使用前缀时,它不会强调属性并将它们视为有效。

这是'data- *'前缀的最初目的。-----点我跳转原回答

那我们就改为ng-init测试下,当我执行ng-init中的代码时,是不是连angular自身的动态dom都加载完成了。

我将ng-init直接绑在了一个需要ng-repeat的ul上,当断点已经执行了我load方法

我去看了此时的dom渲染情况

ul里面一个li都没有,空的,说明根本没解析完成啊,这个方法也就能感知下静态dom渲染,angular的无效,所以不符合我的要求,排除。

 2.$viewContentLoaded事件---无效

大量博客都说了这个方法,那看来是非常的有效啊,去官网查了下api,介绍少之又少

 

英文不好,大概意思是,需要结合ng-view指令使用,只要ng-view指令范围的视图需要重新渲染,通过监听$viewContentLoaded,就能针对改变做你想做的操作了。

<div ng-view></div>

$scope.$on('$viewContentLoaded', function () { //dosomething });

测试了下,代码没执行,又去翻了下资料,怀疑是不是自己用错了,找到了一个关于使用的的特殊说明

当ngView内容被重新加载时,从ngView作用域上发布, 通过$emit将事件沿着作用域向上传播(子作用域到父作用域),也就是说你监听这个事件必须得在那个View的上层作用域。----点我查看原文

也没错啊,将��换成watch还是没效,先不说有没有效,这东西只是说感知ng-view变化时执行,没说dom加载完成后执行,不是我要找的东西。排除在外。

3.自定义指令,$last === true---有bug

因为我做图片懒加载的要求是,在执行懒加载方法前这些img元素都已经渲染好了,我能抓到它们。而这些图片说到底就是通过ng-repeat渲染出来的,既然感知angular dom渲染完成无效,换种思路,能不能得知ng-repeat什么时候渲染完成呢?

通过自定义指令repeatFinish,监听ng-repeat状态。

复制代码
<ul>
    <li ng-repeat="item in data track by $index" repeat-finish></li>
</ul>

angular
.module("mainApp")
.directive('repeatFinish', [function () {
    //判断ng-repeat是否渲染完成的自定义指令,暂时没用到,以后可能会用
    return {
        restrict: 'EA',
        link: function (scope, element, attr) {
            if(scope.$last === true) {
                //dosomething
            };
        },

    };
}]);
复制代码

在ng-repeat过程中,scope作用域中有一个$last的状态变量,当循环到最后一个元素时,它就会变成true,而这个方法是写在link中的,link是为dom绑定相关指令事件的,赶紧去测试下,打个断点

出问题了,我需要循环的数组其实有10条数据,理论上来说,一开始索引$index应该从0开始,但是这里却直接从1开始了,也就是第二条数据,假设我需要循环的数据一共就1条,link里面的函数直接就不触发了。

其次,因为我实际使用是在产品分类页中,点击不同产品分类,被循环的数据data其实是在改变的,有趣的是,假设A类产品有4条,B类产品有3条,由4条切换到3条的过程中,也不会触发link中的函数。

对于这种做法的问题,大概归纳为两点:

一是数据只有1条时监听不到,方法是通用的,谁知道你要遍历的数据有几条。

当需要repeat的数据是可变的,由多变少的过程不会触发,少变多的过程会触发,说到底还是有问题,用不了,有兴趣的同学可以写demo测试下,我暂时也解释不了为什么会这样。

三、靠谱的解决方案

功夫不负有心人,在简书的一篇文章中,找到了可行靠谱的方法,使用$timeout。

复制代码
<ul>
    <li ng-repeat="item in data track by $index"></li>
</ul>

$timeout(function () {
    //处理dom加载完成,或者repeat循环完成要做的事情
},0);
复制代码

原理是什么呢,大家都知道,js的定时器其实也是异步的,其实只是angular为了能自动触发脏检测而封装的方法,同样也是异步。将你需要执行的方法放在timeout中,它就会等到所有的dom渲染完成以及同步逻辑跑完最后执行,真的是让人眼前一亮!

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  125
统信桌面专业版【全盘安装UOS系统】介绍  120
银河麒麟桌面操作系统安装佳能打印机驱动方法  112
银河麒麟桌面操作系统 V10-SP1用户密码修改  105
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益209.03元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!