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 相关文章推荐
jQuery validate 中文API 附validate.js中文api手册
Jul 31 Javascript
javascript一些实用技巧小结
Mar 18 Javascript
JQuery1.6 使用方法三
Nov 23 Javascript
使用js完成节点的增删改复制等的操作
Jan 02 Javascript
如何改进javascript代码的性能
Apr 02 Javascript
jquery实现初次打开有动画效果的网页TAB切换代码
Sep 06 Javascript
jQuery如何防止Ajax重复提交
Oct 14 Javascript
把json格式的字符串转换成javascript对象或数组的方法总结
Nov 03 Javascript
vue响应式系统之observe、watcher、dep的源码解析
Apr 09 Javascript
微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)
Jul 25 Javascript
一篇文章弄懂javascript中的执行栈与执行上下文
Aug 09 Javascript
vue中动态select的使用方法示例
Oct 28 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
IIS+fastcgi下PHP运行超时问题的解决办法详解
2013/06/20 PHP
Smarty变量调节器失效的解决办法
2014/08/20 PHP
PHP滚动日志的代码实现
2015/06/10 PHP
PHP实现通过get方式识别用户发送邮件的方法
2015/07/16 PHP
二级域名转向类
2006/11/09 Javascript
JSON 编辑器实现代码
2009/12/06 Javascript
html中table数据排序的js代码
2011/08/09 Javascript
根据经纬度计算地球上两点之间的距离js实现代码
2013/03/05 Javascript
js中document.write使用过程中的一点疑问解答
2014/03/20 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
使用ajax+jqtransform实现动态加载select
2014/12/01 Javascript
javascript修改图片src的方法
2015/01/27 Javascript
js钢琴按钮波浪式图片排列效果代码分享
2015/08/26 Javascript
AngularJS初始化静态模板详解
2016/01/14 Javascript
VUE JS 使用组件实现双向绑定的示例代码
2017/01/10 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
Vue组件tree实现树形菜单
2017/04/13 Javascript
vue.js实现用户评论、登录、注册、及修改信息功能
2020/05/30 Javascript
捕获未处理的Promise错误方法
2017/10/13 Javascript
Vue 与 Vuex 的第一次接触遇到的坑
2018/08/16 Javascript
JavaScript数值类型知识汇总
2019/11/17 Javascript
JS实现盒子拖拽效果
2020/02/06 Javascript
在js文件中引入(调用)另一个js文件的三种方法
2020/09/11 Javascript
[31:47]夜魇凡尔赛茶话会 第三期01:选手知多少
2021/03/11 DOTA
Python requests发送post请求的一些疑点
2018/05/20 Python
Django admin model 汉化显示文字的实现方法
2019/08/12 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
自定义实现 PyQt5 下拉复选框 ComboCheckBox的完整代码
2020/03/30 Python
Python模拟登录requests.Session应用详解
2020/11/17 Python
Python paramiko使用方法代码汇总
2020/11/20 Python
爱情寄语大全
2014/04/09 职场文书
师德标兵事迹材料
2014/12/19 职场文书
协议书范文
2015/01/27 职场文书
文员岗位职责范本
2015/04/16 职场文书
运动员入场前导词
2015/07/20 职场文书
《王国之心》迎来了发售的20周年, 野村哲发布贺图
2022/04/11 其他游戏