使用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 相关文章推荐
Jquery练习之表单验证实现代码
Dec 14 Javascript
jquery实现弹出div,始终显示在屏幕正中间的简单实例
Mar 08 Javascript
JavaScript弹出对话框的三种方式
Mar 23 Javascript
在微信、支付宝、百度钱包实现点击返回按钮关闭当前页面和窗口的方法
Aug 05 Javascript
浅谈js script标签中的预解析
Dec 30 Javascript
vue项目中应用ueditor自定义上传按钮功能
Apr 27 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
Oct 30 Javascript
vue-lazyload使用总结(推荐)
Nov 01 Javascript
jQuery实现的记住帐号密码功能完整示例
Aug 03 jQuery
vue柱状进度条图像的完美实现方案
Aug 26 Javascript
Vue登录主页动态背景短视频制作
Sep 21 Javascript
原生js+canvas实现贪吃蛇效果
Aug 02 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
phpMyAdmin2.11.6安装配置方法
2008/08/24 PHP
phpMyAdmin出现无法载入 mcrypt 扩展,请检查PHP配置的解决方法
2012/03/26 PHP
thinkphp控制器调度使用示例
2014/02/24 PHP
ecshop 2.72如何修改后台访问地址
2015/03/03 PHP
使用PHP开发留言板功能
2019/11/19 PHP
使用户点击后退按钮使效三行代码
2007/07/07 Javascript
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
用jquery实现等比例缩放图片效果插件
2010/07/24 Javascript
麻雀虽小五脏俱全 Dojo自定义控件应用
2010/09/04 Javascript
基于jQuery的可用于选项卡及幻灯的切换插件
2011/03/28 Javascript
javascript在子页面中函数无法调试问题解决方法
2014/01/17 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
jQuery实现摸拟alert提示框
2016/05/22 Javascript
微信js-sdk界面操作接口用法示例
2016/10/12 Javascript
js实现百度地图定位于地址逆解析,显示自己当前的地理位置
2016/12/08 Javascript
Vue实现双向绑定的方法
2016/12/22 Javascript
jQuery日期范围选择器附源码下载
2017/05/23 jQuery
Angular4 组件通讯方法大全(推荐)
2018/07/12 Javascript
VUE基于NUXT的SSR 服务端渲染
2018/11/30 Javascript
Vue初始化中的选项合并之initInternalComponent详解
2020/06/11 Javascript
[04:50]2019DOTA2高校联赛秋季赛四强集锦
2019/12/27 DOTA
Python多线程学习资料
2012/12/19 Python
利用anaconda作为python的依赖库管理方法
2019/08/13 Python
tensorflow入门:TFRecordDataset变长数据的batch读取详解
2020/01/20 Python
tensorflow实现二维平面模拟三维数据教程
2020/02/11 Python
python 使用三引号时容易犯的小错误
2020/10/21 Python
CSS3 实现飘动的云朵动画
2020/12/01 HTML / CSS
工程概预算专业毕业生求职信
2013/10/04 职场文书
交通法规咨询中心工作职责
2013/11/27 职场文书
大学生个人事迹材料
2014/01/21 职场文书
校外活动方案
2014/08/28 职场文书
《我爱祖国》演讲稿1000字
2014/09/26 职场文书
机关干部个人对照检查材料思想汇报
2014/09/28 职场文书
乡镇一岗双责责任书
2015/01/29 职场文书
想创业成功,需要掌握这些要点
2019/12/06 职场文书