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 相关文章推荐
给html超链接设置事件不使用href来完成跳
Apr 20 Javascript
JavaScript常用数组算法小结
Feb 13 Javascript
js 转json格式的字符串为对象或数组(前后台)的方法
Nov 02 Javascript
实现JavaScript高性能的数据存储
Dec 11 Javascript
Javascript实现信息滚动效果
May 18 Javascript
JS实现给json数组动态赋值的方法示例
Mar 19 Javascript
Vue登录注册并保持登录状态的方法
Aug 17 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
Nov 19 Javascript
vue-for循环嵌套操作示例
Jan 28 Javascript
Angular脚手架开发的实现步骤
Apr 09 Javascript
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
Sep 28 Javascript
element多个表单校验的实现
May 27 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
mysql 中InnoDB和MyISAM的区别分析小结
2008/04/15 PHP
给初学者的30条PHP最佳实践(荒野无灯)
2011/08/02 PHP
PHP合并两个数组的两种方式的异同
2012/09/14 PHP
10 个经典PHP函数
2013/10/17 PHP
PHP获取音频文件的相关信息
2015/06/22 PHP
Smarty保留变量用法分析
2016/05/23 PHP
PHP中功能强大却很少使用的函数实例小结
2016/11/10 PHP
PHP强制转化的形式整理
2020/05/22 PHP
JavaScript为对象原型prototype添加属性的两种方式
2010/08/01 Javascript
JavaScript闭包 懂不懂由你反正我是懂了
2011/10/21 Javascript
Jquery 数组操作大全个人总结
2013/11/13 Javascript
JS动态生成年份和月份实例代码
2017/02/04 Javascript
微信小程序 扎金花简单实例
2017/02/21 Javascript
Vue 父子组件、组件间通信
2017/03/08 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
2017/09/10 Javascript
Nuxt.js开启SSR渲染的教程详解
2018/11/30 Javascript
mocha的时序规则讲解
2019/02/16 Javascript
怎样使你的 JavaScript 代码简单易读(推荐)
2019/04/16 Javascript
python optparse模块使用实例
2015/04/09 Python
利用Python中的mock库对Python代码进行模拟测试
2015/04/16 Python
举例讲解Python中装饰器的用法
2015/04/27 Python
python构建自定义回调函数详解
2017/06/20 Python
浅谈Python黑帽子取代netcat
2018/02/10 Python
Python 实现还原已撤回的微信消息
2019/06/18 Python
Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
2019/12/04 Python
利用matplotlib为图片上添加触发事件进行交互
2020/04/23 Python
Python爬取微信小程序通用方法代码实例详解
2020/09/29 Python
记一次高分屏下canvas模糊问题
2020/02/17 HTML / CSS
南京某软件公司的.net面试题
2015/11/30 面试题
金鑫耀Java笔试题
2014/09/06 面试题
Delphi工程师笔试题
2013/09/21 面试题
汉语言文学职业规划
2014/02/14 职场文书
大学理论知识学习自我鉴定
2014/04/28 职场文书
学校先进集体事迹材料
2014/05/31 职场文书
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle