JS如何监听div的resize事件详解


Posted in Javascript onDecember 03, 2020

需求

开发过程中经常遇到的一个问题就是如何监听一个div的size变化。
比如我用canvas绘制了一个chart,当canvas的size发生变化的时候,需要重新绘制里面的内容,这个时候就需要监听resize事件做处理。

window上虽然可以添加resize事件监听,但这并不能满足我们的需求,因为很多时候,div的size发生了变化,但是window的size并没有改变。

不过我们可以间接利用window的resize事件监听来实现对于某个div的resize事件监听,请看下面具体实现。

对于div的resize事件的监听,实现方式有很多,比如周期性检查,通过scroll事件等等,本文主要介绍通过object元素来实现监听。

具体实现

/**
 * Created by taozh on 2017/5/6.
 * taozh1982@gmail.com
 */
var EleResize = {
 _handleResize: function (e) {
  var ele = e.target || e.srcElement;
  var trigger = ele.__resizeTrigger__;
  if (trigger) {
   var handlers = trigger.__z_resizeListeners;
   if (handlers) {
    var size = handlers.length;
    for (var i = 0; i < size; i++) {
     var h = handlers[i];
     var handler = h.handler;
     var context = h.context;
     handler.apply(context, [e]);
    }
   }
  }
 },
 _removeHandler: function (ele, handler, context) {
  var handlers = ele.__z_resizeListeners;
  if (handlers) {
   var size = handlers.length;
   for (var i = 0; i < size; i++) {
    var h = handlers[i];
    if (h.handler === handler && h.context === context) {
     handlers.splice(i, 1);
     return;
    }
   }
  }
 },
 _createResizeTrigger: function (ele) {
  var obj = document.createElement('object');
  obj.setAttribute('style',
   'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;');
  obj.onload = EleResize._handleObjectLoad;
  obj.type = 'text/html';
  ele.appendChild(obj);
  obj.data = 'about:blank';
  return obj;
 },
 _handleObjectLoad: function (evt) {
  this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
  this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
 }
};
if (document.attachEvent) {//ie9-10
 EleResize.on = function (ele, handler, context) {
  var handlers = ele.__z_resizeListeners;
  if (!handlers) {
   handlers = [];
   ele.__z_resizeListeners = handlers;
   ele.__resizeTrigger__ = ele;
   ele.attachEvent('onresize', EleResize._handleResize);
  }
  handlers.push({
   handler: handler,
   context: context
  });
 };
 EleResize.off = function (ele, handler, context) {
  var handlers = ele.__z_resizeListeners;
  if (handlers) {
   EleResize._removeHandler(ele, handler, context);
   if (handlers.length === 0) {
    ele.detachEvent('onresize', EleResize._handleResize);
    delete ele.__z_resizeListeners;
   }
  }
 }
} else {
 EleResize.on = function (ele, handler, context) {
  var handlers = ele.__z_resizeListeners;
  if (!handlers) {
   handlers = [];
   ele.__z_resizeListeners = handlers;

   if (getComputedStyle(ele, null).position === 'static') {
    ele.style.position = 'relative';
   }
   var obj = EleResize._createResizeTrigger(ele);
   ele.__resizeTrigger__ = obj;
   obj.__resizeElement__ = ele;
  }
  handlers.push({
   handler: handler,
   context: context
  });
 };
 EleResize.off = function (ele, handler, context) {
  var handlers = ele.__z_resizeListeners;
  if (handlers) {
   EleResize._removeHandler(ele, handler, context);
   if (handlers.length === 0) {
    var trigger = ele.__resizeTrigger__;
    if (trigger) {
     trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
     ele.removeChild(trigger);
     delete ele.__resizeTrigger__;
    }
    delete ele.__z_resizeListeners;
   }
  }
 }
}

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Resize</title>
 <script src="./EleResize.js"></script>
 <style>
  html, body {
   margin: 0;
   padding: 0;
   width: 100%;
   height: 100%;
  }

  #resizeDiv {
   width: 60%;
   height: 60%;
   border: 1px solid red;
   margin: 20px;
  }

  button {
   margin: 20px 20px 0;
  }
 </style>
</head>
<body>
<button onclick="addListener()">addListener</button>
<button onclick="removeListener()">removeListener</button>
<button onclick="resize()">resize</button>
<div id="resizeDiv"></div>
<script>
 var resizeDiv = document.getElementById('resizeDiv');
 function resize() {
  resizeDiv.style.width = "200px";
 }
 var listener = function () {
  console.log("resize");
 };
 function addListener() {
  EleResize.on(resizeDiv, listener);
 }
 function removeListener() {
  EleResize.off(resizeDiv, listener)
 }
</script>
</body>
</html>

原理

这里的具体实现分两类,

  • ie9-10

默认支持div的resize事件,可以直接通过div.attachEvent('onresize', handler);的方式实现

  • 其它浏览器

通过在div中添加一个内置object元素实现监听。

设置object元素的style使其填充满div,这样当div的size发生变化时,object的size也会发生变化。

然后监听object元素的contentDocument.defaultView(window对象)的resize事件。

注:本文提供的是如何监听resize事件,其实在resize时,可能会连续快速的触发(比如拖动浏览器),为了提高效率,可以考虑使用批处理的模式。

到此这篇关于JS如何监听div的resize事件的文章就介绍到这了,更多相关JS监听div的resize事件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js实现点小图看大图效果的思路及示例代码
Oct 28 Javascript
JSON取值前判断
Dec 23 Javascript
JavaScript定时器和优化的取消定时器方法
Jul 03 Javascript
JS正则表达式比较常见用法
Jan 26 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
Jul 12 Javascript
jQuery使用unlock.js插件实现滑动解锁
Apr 04 jQuery
聊聊JavaScript如何实现继承及特点
Apr 07 Javascript
Node.js实现发送邮件功能
Nov 06 Javascript
AngularJs 最新验证手机号码的实例,成功测试通过
Nov 26 Javascript
深入理解react-router 路由的实现原理
Sep 26 Javascript
解决layer.confirm快速点击会重复触发事件的问题
Sep 23 Javascript
利用JS如何获取form表单数据
Dec 19 Javascript
JavaScript十大取整方法实例教程
Dec 03 #Javascript
js实现圆形菜单选择器
Dec 03 #Javascript
Javascript新手入门之字符串拼接与变量的应用
Dec 03 #Javascript
vue表单验证之禁止input输入框输入空格
Dec 03 #Vue.js
微信小程序实现首页弹出广告
Dec 03 #Javascript
为什么JavaScript中0.1 + 0.2 != 0.3
Dec 03 #Javascript
基于javascript实现放大镜特效
Dec 03 #Javascript
You might like
通过Email发送PHP错误的方法
2015/07/20 PHP
PHP学习记录之数组函数
2018/06/01 PHP
PHP curl批处理及多请求并发实现方法分析
2018/08/15 PHP
PHP实现微信商户支付企业付款到零钱功能
2018/09/30 PHP
javascript生成/解析dom的CDATA类型的字段的代码
2007/04/22 Javascript
javascript 内存回收机制理解
2011/01/17 Javascript
js全选实现和判断是否有复选框选中的方法
2015/02/17 Javascript
jquery获取复选框checkbox的值实现方法
2016/05/30 Javascript
JavaScript每天必学之数组和对象部分
2016/09/17 Javascript
jQuery时间日期三级联动(推荐)
2016/11/27 Javascript
js倒计时小实例(多次定时)
2016/12/08 Javascript
AngularJS的$location使用方法详解
2017/10/19 Javascript
Angular2的管道Pipe的使用方法
2017/11/07 Javascript
浅谈ES6 模板字符串的具体使用方法
2017/11/07 Javascript
js console.log打印对象时属性缺失的解决方法
2019/05/23 Javascript
vue在App.vue文件中监听路由变化刷新页面操作
2020/08/14 Javascript
[03:54]DOTA2英雄梦之声_第06期_昆卡
2014/06/23 DOTA
[00:31]DOTA2荣耀之路7:Miracle-空血无敌斩
2018/05/31 DOTA
Python递归遍历列表及输出的实现方法
2015/05/19 Python
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
Python中is与==判断的区别
2017/03/28 Python
python Pandas 读取txt表格的实例
2018/04/29 Python
浅谈Keras的Sequential与PyTorch的Sequential的区别
2020/06/17 Python
python中np是做什么的
2020/07/21 Python
python 自动识别并连接串口的实现
2021/01/19 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
HTML5 新标签全部总汇(推荐)
2016/06/13 HTML / CSS
中英文求职信范文
2014/01/27 职场文书
学习教师法的心得体会
2014/09/03 职场文书
刑事辩护授权委托书
2014/09/13 职场文书
大学生个人学习总结
2015/02/15 职场文书
常住证明范本
2015/06/23 职场文书
保护地球的宣传语
2015/07/13 职场文书
行为习惯主题班会
2015/08/14 职场文书
丧事答谢词大全
2015/09/30 职场文书
nginx配置文件使用环境变量的操作方法
2021/06/02 Servers