angular监听dom渲染完成,判断ng-repeat循环完成
一、前言
最近做了一个图片懒加载的小插件,功能需要dom渲染完成后,好获取那些需要懒加载的dom元素。那么问题来了,如果只是感知静态的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的上层作用域。----点我查看原文
也没错啊,将$on换成$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的定时器其实也是异步的,$timeout其实只是angular为了能自动触发脏检测而封装的方法,同样也是异步。将你需要执行的方法放在$timeout中,它就会等到所有的dom渲染完成以及同步逻辑跑完最后执行,真的是让人眼前一亮!
方案出处 实现AngularJS渲染完毕后执行脚本
四、关于写博客的自我反应
在我查解决方案的过程中,我确实是被一些博客弄的特别烦躁和恼火,文章内容全靠复制,代码自己不试验,比如谈到$viewContentLoaded几乎没有人提都没提这个东西是结合ng-view使用的,内容全是大同小异,怎么用也不说清楚,复制粘贴来的东西终究是别人的,那这篇博客的产出说到底浪费自己和读者的时间。这也提醒了我自己,对于以后的博客编写,涉及到代码相关的,一定亲自试验,保证可用。
学习不是一天两天,没有捷径,唯有积累。
angular监听dom渲染完成,判断ng-repeat循环完成的更多相关文章
- angular指令监听ng-repeat渲染完成后执行自定义事件方法
今天工作中遇到需要用到ng-repeat遍历渲染完后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己创建自定义指令. 在ng-repeat模板实例内部会暴露 ...
- 利用angular指令监听ng-repeat渲染完成后执行脚本
业务中有时需要在异步获取数据并用ng-repeat遍历渲染完页面后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己动手写.有经验的同学都应该知道,在ng-r ...
- Angular 监听路由变化
var app = angular.module('Mywind',['ui.router']) //Angular 监听路由变化 function run($ionicPlatform, $loca ...
- JS监听DOM结构变化
在做一个微博的接入,需要判断微博是否被关注,要检查微博标签的DIV是否有“已关注”的字符,但这个DIV的内容是微博JSSDK动态生成.$("#id").html()是获取不到我想要 ...
- javascript 原生方法监听DOM结构改变事件
js原生方法监听DOM结构改变事件 document.addEventListener('DOMNodeInserted',function(){alert(1)},false);document.a ...
- js动态监听dom变化
原生js 动态监听dom变化,根据不同的类型绑定不同的处理逻辑 // Firefox和Chrome早期版本中带有前缀 var MutationObserver = window.MutationO ...
- jQuery学习(监听DOM加载)
jQuery的extend方法 function njQuery() { } /* njQuery.extend = function (obj) { // 此时此刻的this就是njQuery这个类 ...
- MutationObserver 监听DOM树变化
1 概述 Mutation observer 是用于代替 Mutation events 作为观察DOM树结构发生变化时,做出相应处理的API.为什么要使用mutation observer 去代替 ...
- js实时监听dom尺寸变化
开发过程中总会遇到dom节点尺寸变化,去做一些相应的逻辑,第一想到的应该是用$(window).resize()去做,但是这个是监听浏览器窗口的所以这个时候要用 ResizeObserver Resi ...
随机推荐
- 摹客iDoc「标注」新玩法!这些细节让你爱不释手(201903-2版本更新)
哈喽小伙伴们,我们又见面啦!没错,小摹就是来告诉大家:摹客iDoc又双叒叕升级了!这次又上线了许多新玩法,在此之前,小摹先带大家温习一下iDoc以往的知识点: 攻城狮查看标注的利器 —— 标注信息智能 ...
- 1.5eigen中高级初始化
1.5 高级初始化 这一节讨论一些初始化矩阵的高级方法. 1.The comma initializer eigen提供一个简单设定所有矩阵系数.向量.数组系数的初始化语法,从左上角开始到右下角结束. ...
- 20175316盛茂淞 迭代和JDB
迭代和JDB 题目 1 使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能 2 m,n 要通过命令行传入 3 提交测试运行截图(至少三张:正常如c( ...
- delphi 中OutputDebugString 函数的妙用(转载)
原文地址 https://www.peganza.com/delphi-and-outputdebugstring.html Ever wanted to monitor your Delphi ap ...
- c++类对象的内存分布
要想知道c++类对象的内存布局, 可以有多种方式,比如: 1)输出成员变量的偏移, 通过offsetof宏来得到 2)通过调试器查看, 比如常用的VS 1.没有数据成员的对象 class A{ }; ...
- 其于OpenXml SDK写的帮助类
/// <summary> /// 其于OpenXml SDK写的帮助类 /// </summary> public static class OpenXmlHelper { ...
- EF6学习笔记(四) 弹性连接及命令拦截调试
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...
- UBUNTU14.0.4安装eclipse
jdk工具下载地址 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 点击这个下载 ...
- MFC开发中添加自定义消息和消息响应函数
(1)在.h或.cpp文件定义一个消息 #define CLICK_MESSAGE_BOX WM_USER+1001 //add by 20180612 给主窗口ctrl.cpp发送消息 //自定义消 ...
- Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
原文出处: 海子 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅 ...