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 相关文章推荐
给Function做的OOP扩展
May 07 Javascript
一些相见恨晚的 JavaScript 技巧
Apr 25 Javascript
Javascript 类、命名空间、代码组织代码
Jul 31 Javascript
jquery+ajax+C#实现无刷新操作数据库数据的简单实例
Feb 08 Javascript
JS判断文本框内容改变事件的简单实例
Mar 07 Javascript
JavaScript实现的石头剪刀布游戏源码分享
Aug 22 Javascript
详解js的六大数据类型
Dec 27 Javascript
通过jquery toggleClass()属性制作文章段落更改背景颜色
May 21 jQuery
详解js的视频和音频采集
Aug 09 Javascript
vue中Axios的封装与API接口的管理详解
Aug 09 Javascript
jQuery实现移动端图片上传预览组件的方法分析
May 01 jQuery
简单了解vue 插值表达式Mustache
Jul 22 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
正义联盟的终局之战《天启星战争》将成为DC动画宇宙的最后一部
2020/04/09 欧美动漫
PHP判断表单复选框选中状态完整例子
2014/06/24 PHP
php metaphone()函数的定义和用法
2016/05/15 PHP
PHP+mysql实现的三级联动菜单功能示例
2019/02/15 PHP
Javascript 篱式条件判断
2008/08/22 Javascript
javascript 显示当前系统时间代码
2009/12/28 Javascript
jQuery Mobile页面跳转后未加载外部JS原因分析及解决
2013/03/18 Javascript
浅谈JavaScript之事件绑定
2013/07/08 Javascript
JS检测图片大小的实例
2013/08/21 Javascript
form.submit()不能提交表单的错误原因及解决方法
2014/10/13 Javascript
JS+CSS实现模仿浏览器网页字符查找功能的方法
2015/02/26 Javascript
简化版手机端照片预览组件
2015/04/13 Javascript
JS实现DIV容器赋值的方法
2015/12/14 Javascript
jQuery如何获取动态添加的元素
2016/06/24 Javascript
详解jQuery停止动画——stop()方法的使用
2016/12/14 Javascript
详解Python中logging日志模块在多进程环境下的使用
2016/12/26 Javascript
Angular2使用Guard和Resolve进行验证和权限控制
2017/04/24 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
Vue中的scoped实现原理及穿透方法
2018/05/15 Javascript
vue项目中jsonp跨域获取qq音乐首页推荐问题
2018/05/30 Javascript
Vue中的混入的使用(vue mixins)
2018/06/01 Javascript
JS实现二维数组元素的排列组合运算简单示例
2019/01/28 Javascript
用PyQt进行Python图形界面的程序的开发的入门指引
2015/04/14 Python
python中map()函数的使用方法示例
2017/09/29 Python
Python logging设置和logger解析
2019/08/28 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
2020/01/08 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
python读取excel进行遍历/xlrd模块操作
2020/07/12 Python
Python同时处理多个异常的方法
2020/07/28 Python
接口的多继承会带来哪些问题
2015/08/17 面试题
自荐书模板
2013/12/15 职场文书
《宋庆龄故居的樟树》教学反思
2014/04/07 职场文书
装修协议书范本
2014/04/21 职场文书
教学督导岗位职责
2015/04/10 职场文书
redis限流的实际应用
2021/04/24 Redis
Python Django框架介绍之模板标签及模板的继承
2021/05/27 Python