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 相关文章推荐
IE事件对象(The Internet Explorer Event Object)
Jun 27 Javascript
JS将制定内容复制到剪切板示例代码
Feb 11 Javascript
jquery实现带二级菜单的导航示例
Apr 28 Javascript
javascript去除字符串中所有标点符号和提取纯文本的正则
Jun 07 Javascript
jQuery CSS()方法改变现有的CSS样式表
Sep 09 Javascript
javascript学习笔记(一)基础知识
Sep 30 Javascript
Node.js的Web模板引擎ejs的入门使用教程
Jun 06 Javascript
Bootstrap零基础入门教程(三)
Jul 18 Javascript
将 vue 生成的 js 上传到七牛的实例
Jul 28 Javascript
利用JavaScript缓存远程窃取Wi-Fi密码的思路详解
Nov 05 Javascript
浅谈js闭包理解
Apr 01 Javascript
在vue中使用axios实现post方式获取二进制流下载文件(实例代码)
Dec 16 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
PHP5与MySQL数据库操作常用代码 收集
2010/03/21 PHP
浅析linux下apache服务器的配置和管理
2013/08/10 PHP
PHP strip_tags()去除HTML、XML以及PHP的标签介绍
2014/02/18 PHP
php常用文件操作函数汇总
2014/11/22 PHP
PHP中array_slice函数用法实例详解
2014/11/25 PHP
PHP中余数、取余的妙用
2015/06/29 PHP
一个简单的php MVC留言本实例代码(必看篇)
2016/09/22 PHP
PHP+ajax实现获取新闻数据简单示例
2018/05/08 PHP
一个可以随意添加多个序列的tag函数
2009/07/21 Javascript
只需一行代码,轻松实现一个在线编辑器
2013/11/12 Javascript
一个JavaScript用逗号分割字符串实例
2014/09/22 Javascript
JavaScript Math.ceil 方法(对数值向上取整)
2015/01/09 Javascript
Vue.js实现简单ToDoList 前期准备(一)
2016/12/01 Javascript
微信小程序 MD5加密登录密码详解及实例代码
2017/01/12 Javascript
ES6中class类用法实例浅析
2017/04/06 Javascript
vue过滤器实现日期格式化的案例分析
2020/07/02 Javascript
[03:44]2015国际邀请赛选手档案—Cloud9.NoTail
2015/07/28 DOTA
[50:12]EG vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python最基本的输入输出详解
2015/04/25 Python
Python判断直线和矩形是否相交的方法
2015/07/14 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
2017/12/19 Python
python处理csv数据动态显示曲线实例代码
2018/01/23 Python
解决Python pandas df 写入excel 出现的问题
2018/07/04 Python
Python enumerate函数功能与用法示例
2019/03/01 Python
Python ATM功能实现代码实例
2020/03/19 Python
Python tkinter实现简单加法计算器代码实例
2020/05/13 Python
Hotels.com印度:酒店预订
2019/05/11 全球购物
MyBag中文网:英国著名的时尚包袋电商零售网站
2020/07/31 全球购物
个人简历自我评价八例
2013/10/31 职场文书
项目经理聘任书
2014/03/29 职场文书
大一新生学期自我评价
2014/04/09 职场文书
清明节演讲稿
2014/05/27 职场文书
国际贸易毕业生求职信
2014/07/20 职场文书
事业单位工作人员年度考核个人总结
2015/02/12 职场文书
导游词之永济鹳雀楼
2020/01/16 职场文书
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis