使用jQuery监听DOM元素大小变化


Posted in Javascript onFebruary 24, 2016

起因

今天写页面的时候突然有这么个需求,由于父元素(一个DIV)的height是由javascript计算出来的固定的值,而在其中增加了一个多说插件,在用户评论后,子元素(DIV)的height属性增加,导致子元素溢出。但是又不知道如何为多说的评论按钮增加回调函数,于是乎就想到了根据子元素的大小变化来重新计算父元素的height。

onresize?

平常,都是在整个浏览器窗口变化时触发一个修改布局的回调函数。使用的是window对象的resize事件,利用:

window.onresize = callback;

来绑定。但根据resize事件的target是defaultView (window),这里详见MDN的resize文档,也就是说只有window对象有resize事件,于是乎就想到使用jQuery自己的事件机制来模拟一个普通元素上的resize事件

使用JQUERY事件的实现思路

可以想到一种比较简单的方式:

1. 在元素绑定resize对象时,记录元素的width和height
2. 使用requestAnimationFrame、setTimeout、setInterval,每隔一段时间查询其width和height,如果和记录的width和height不一样,运行回调函数并更新记录中的width为height

JQUERY插件

这个功能Ben Alman编写了一个jQuery插件,传送门
该插件的代码(核心部分),详细代码请查看Ben Alman博客的内容:

(function($, window, undefined) {
 var elems = $([]),
  jq_resize = $.resize = $.extend($.resize, {}),
  timeout_id,
  str_setTimeout = 'setTimeout',
  str_resize = 'resize',
  str_data = str_resize + '-special-event',
  str_delay = 'delay',
  str_throttle = 'throttleWindow';
 jq_resize[str_delay] = 250;
 jq_resize[str_throttle] = true;
 $.event.special[str_resize] = {
  setup: function() {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var elem = $(this);
   elems = elems.add(elem);
   $.data(this, str_data, {
    w: elem.width(),
    h: elem.height()
   });
   if (elems.length === 1) {
    loopy();
   }
  },
  teardown: function() {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var elem = $(this);
   elems = elems.not(elem);
   elem.removeData(str_data);
   if (!elems.length) {
    clearTimeout(timeout_id);
   }
  },
  add: function(handleObj) {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var old_handler;
   function new_handler(e, w, h) {
    var elem = $(this),
     data = $.data(this, str_data);
    data.w = w !== undefined ? w : elem.width();
    data.h = h !== undefined ? h : elem.height();
    old_handler.apply(this, arguments);
   }
   if ($.isFunction(handleObj)) {
    old_handler = handleObj;
    return new_handler;
   } else {
    old_handler = handleObj.handler;
    handleObj.handler = new_handler;
   }
  }
 };

 function loopy() {
  timeout_id = window[str_setTimeout](function() {
   elems.each(function() {
    var elem = $(this),
     width = elem.width(),
     height = elem.height(),
     data = $.data(this, str_data);
    if (width !== data.w || height !== data.h) {
     elem.trigger(str_resize, [data.w = width, data.h = height]);
    }
   });
   loopy();
  }, jq_resize[str_delay]);
 }
})(jQuery, this);

jQuery为jQuery插件的开发者提供了添加自定义事件的接口,详细可以参考jQuery官方文档,这里就是典型的jQuery自定义事件添加方式,其中有三个钩子:

1. setup:The setup hook is called the first time an event of a particular type is attached to an element.首次绑定时执行,如果返回 false,使用默认方式绑定事件
2. teardown:The teardown hook is called when the final event of a particular type is removed from an element.若指定该方法,其在移除事件处理程序(removeEventListener)前执行,如果返回 false,移除默认绑定事件
3. add:Each time an event handler is added to an element through an API such as .on(), jQuery calls this hook.每一次给元素绑定事件,都会执行这个方法

setup、teardown和add三个钩子,每个钩子最先做的事都是检测是否该对象为window对象,然后根据window对象特殊处理,因为window对象本身有resize事件

从setup钩子可以看到,在初始化整个事件处理时,创建一个元素队列,队列中的每隔元素都把width和height放在data中,然后每隔250ms启动loopy函数,在loopy函数中判断是否变化,如果有变,触发回调函数并更新data中的width和height

从teardown钩子可以看到,在元素移除事件时,只需要将元素从元素队列移除,并清除元素中的data数据。如果是元素队列中的最后一个元素,则不再继续执行loopy

add钩子中,对回调函数进行了包装

由此可以看到一个简单的jQuery自定义函数的实现机制

Javascript 相关文章推荐
在视频前插入广告
Nov 20 Javascript
JavaScript对象、属性、事件手册集合方便查询
Jul 04 Javascript
JSON辅助格式化处理方法
Mar 26 Javascript
jQuery图片滚动图片的效果(另类实现)
Jun 02 Javascript
JS 按钮点击触发(兼容IE、火狐)
Aug 07 Javascript
extjs 如何给column 加上提示
Jul 29 Javascript
jQuery实现的个性化返回底部与返回顶部特效代码
Oct 30 Javascript
jquery 无限极下拉菜单的简单实例(精简浓缩版)
May 31 Javascript
原生JS查找元素的方法(推荐)
Nov 22 Javascript
jQuery制作全屏宽度固定高度轮播图(实例讲解)
Jul 08 jQuery
利用weixin-java-miniapp生成小程序码并直接返回图片文件流的方法
Mar 29 Javascript
使用原生JS实现火锅点餐小程序(面向对象思想)
Dec 10 Javascript
JavaScript中的闭包
Feb 24 #Javascript
jQuery中判断对象是否存在的方法汇总
Feb 24 #Javascript
jquery中键盘事件小结
Feb 24 #Javascript
javascript实现九宫格相加数值相等
May 28 #Javascript
Javascript类型转换的规则实例解析
Feb 23 #Javascript
理解Javascript图片预加载
Feb 23 #Javascript
Bootstarp风格的toggle效果分享
Feb 23 #Javascript
You might like
PHP生成自定义长度随机字符串的函数分享
2014/05/04 PHP
php自定义函数br2nl实现将html中br换行符转换为文本输入中换行符的方法【与函数nl2br功能相反】
2017/02/17 PHP
php防止sql注入的方法详解
2017/02/20 PHP
thinkphp关于简单的权限判定方法
2017/04/03 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
2020/09/17 PHP
Web版彷 Visual Studio 2003 颜色选择器
2007/01/09 Javascript
js option删除代码集合
2008/11/12 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
2013/08/23 Javascript
从QQ网站中提取的纯JS省市区三级联动菜单
2013/12/25 Javascript
初识Node.js
2015/03/20 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
2015/09/07 Javascript
JavaScript sort数组排序方法和自我实现排序方法小结
2016/06/06 Javascript
jQuery中弹出iframe内嵌页面元素到父页面并全屏化的实例代码
2016/12/27 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
JS与HTML结合实现流程进度展示条思路详解
2017/09/03 Javascript
微信小程序实现圆形进度条动画
2020/11/18 Javascript
基于JavaScript实现随机点名器
2021/02/25 Javascript
python装饰器使用方法实例
2013/11/21 Python
解决python写的windows服务不能启动的问题
2014/04/15 Python
简单解决Python文件中文编码问题
2015/11/22 Python
Python 多线程的实例详解
2017/09/07 Python
详解windows python3.7安装numpy问题的解决方法
2018/08/13 Python
基于python实现的百度音乐下载器python pyqt改进版(附代码)
2019/08/05 Python
解决python中0x80072ee2错误的方法
2020/07/19 Python
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
css3弹性盒模型实例介绍
2013/05/27 HTML / CSS
html5 Canvas画图教程(11)—使用lineTo/arc/bezierCurveTo画椭圆形
2013/01/09 HTML / CSS
仿酷狗html5手机音乐播放器主要部分代码
2013/05/15 HTML / CSS
百思买美国官网:Best Buy
2016/07/28 全球购物
静态变量和实例变量的区别
2015/07/07 面试题
运动会通讯稿150字
2014/02/15 职场文书
贷款承诺书范文
2014/05/19 职场文书
2016领导干部廉洁自律心得体会
2016/01/13 职场文书
2019职场实习报告该怎么写?
2019/07/01 职场文书
世界十大评分最高的动漫,CLANNAD上榜,第八赚足人们眼泪
2022/03/18 日漫
i5-10400f处理相当于i7多少水平
2022/04/19 数码科技