JavaScript监听一个DOM元素大小变化


Posted in Javascript onApril 26, 2020

1.需求场景

开发过程中经常遇到的一个问题就是如何监听一个 div 的size变化。
比如我用canvas绘制了一个chart,当canvas的size发生变化的时候,需要重新绘制里面的内容,这个时候就需要监听resize事件做处理。window上虽然有resize事件监听,但这并不能满足我们的需求,因为很多时候,div的size发生了变化,实际 window.resize 事件并未触发。
对于div的resize事件的监听,实现方式有很多,比如定时器检查,通过scroll事件等等,本文主要介绍通过iframe 元素来实现监听。
不过我们可以间接利用window的resize事件监听来实现对于某个div的resize事件监听,请看下面具体实现。

2. 实现原理

  • 动态创建 iframe 标签,追加到容器中,宽高继承容器100%;
  • 获取 iframe 中的window,通过 contentWindow 属性就能获取到;
  • 由于 iframe 的宽高继承与父节点,当父容器宽度发生变化,自然会触发iframe中的resize 事件;

通过 iframeWindow.resize 事件来监听DOM大小变化,从而达到resize事件的一个监听;

例子

document.querySelector("#ifarme_id").contentWindow.addEventListener('resize', () => {
  console.log('size Change!');
}, false)

3.调用

<!DOCTYPE html>
<html>
  <head>
 <meta charset="utf-8">
 <title>DIV宽高监听</title>
  <style type="text/css">
    #content {
    overflow: auto;
  }
 </style>
 </head>
 <body>
 <div id="content">
      钟南山:非洲如果预防得好,天热时疫情会下降
     另外,会上有外籍人士提问:假如你现在去非洲,首先要做的是什么?
     钟南山表示:现在要做的是防护,防止蔓延是最重要的。
     在非洲,这段时间如果预防得好,也可能到天热时,疫情发展情况会下降。
 </div>

 <button id="change-size">改变宽高</button>

 <script type="text/javascript">
  var eleResize = new ElementResize('#content');
  eleResize.listen(function() {
  console.log('size change!')
  })

  //改变宽高
  document.querySelector('#change-size').addEventListener('click', function() {
  let cont = document.querySelector('#content');
  cont.style.width = Math.floor((Math.random() * (document.documentElement.clientWidth - 500)) + 500) + 'px';
  cont.style.height = Math.floor(Math.random() * 300) + 'px';
  }, false)
 </script>
 </body>
</html>

完整代码

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>DIV宽高监听</title>
 <style type="text/css">
  #content {
  overflow: auto;
  }
 </style>
 </head>
 <body>
 <div id="content">
  钟南山:非洲如果预防得好,天热时疫情会下降

  另外,会上有外籍人士提问:假如你现在去非洲,首先要做的是什么?

  钟南山表示:现在要做的是防护,防止蔓延是最重要的。

  在非洲,这段时间如果预防得好,也可能到天热时,疫情发展情况会下降。
 </div>
 <button id="change-size">改变宽高</button>

 <script type="text/javascript">
  (function() {
  let self = this;
  /**
   * 元素宽高监听
   * @param {Object} el 监听元素选择器
   */
  function ElementResize(eleSelector) {
   if (!(this instanceof ElementResize)) return;
   if (!eleSelector) return;
   this.eleSelector = eleSelector;
   this.el = document.querySelector(eleSelector);
   this.queue = [];
   this.__init(); //globel init
  }

  //初始化
  ElementResize.prototype.__init = function() {
   let iframe = this.crateIElement();
   this.el.style.position = 'relative';
   this.el.appendChild(iframe)
   this.bindEvent(iframe.contentWindow);
  }

  /**
   * 设置元素样式
   * @param {HTMLObject} el
   * @param {Object} styleJson
   */
  ElementResize.prototype.setStyle = function(el, styleJson) {
   if (!el) return;
   styleJson = styleJson || {
   opacity: 0,
   'z-index': '-1111',
   position: 'absolute',
   left: 0,
   top: 0,
   width: '100%',
   height: '100%',
   };
   let styleText = '';
   for (key in styleJson) {
   styleText += (key + ':' + styleJson[key] + ';');
   }
   el.style.cssText = styleText;
  }

  /**
   * 创建元素
   * @param {Object} style
   */
  ElementResize.prototype.crateIElement = function(style) {
   let iframe = document.createElement('iframe');
   this.setStyle(iframe);
   return iframe;
  }

  /**
   * 绑定事件
   * @param {Object} el
   */
  ElementResize.prototype.bindEvent = function(el) {
   if (!el) return;
   var _self = this;
   el.addEventListener('resize', function() {
   _self.runQueue();
   }, false)
  }

  /**
   * 运行队列
   */
  ElementResize.prototype.runQueue = function() {
   let queue = this.queue;
   for (var i = 0; i < queue.length; i++) {
   (typeof queue[i]) === 'function' && queue[i].apply(this);
   }
  }

  /**
   * 外部监听
   * @param {Object} cb 回调函数
   */
  ElementResize.prototype.listen = function(cb) {
   if (typeof cb !== 'function') throw new TypeError('cb is not a function!');
   this.queue.push(cb);
  }

  self.ElementResize = ElementResize;
  })()
  
  //创建一个监听实例
  var eleResize = new ElementResize('#content');
  eleResize.listen(function() {
  console.log('我是listener')
  })

  //宽高切换
  document.querySelector('#change-size').addEventListener('click', function() {
  let cont = document.querySelector('#content');
  cont.style.width = Math.floor((Math.random() * (document.documentElement.clientWidth - 500)) + 500) + 'px';
  cont.style.height = Math.floor(Math.random() * 300) + 'px';
  }, false)
 </script>
 </body>
</html>

到此这篇关于JavaScript监听一个DOM元素大小变化的文章就介绍到这了,更多相关JavaScript监听DOM元素大小内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Jquery:ajax实现翻页无刷新功能代码
Aug 05 Javascript
jquery mobile事件多次绑定示例代码
Sep 13 Javascript
js获取当月最后一天实例代码
Nov 19 Javascript
深入分析Javascript跨域问题
Apr 17 Javascript
jquery+CSS3实现3D拖拽相册效果
Jul 18 Javascript
discuz表情的JS提取方法分析
Mar 22 Javascript
Node.js实现文件上传的示例
Jun 28 Javascript
Vue组件开发之LeanCloud带图形校验码的短信发送功能
Nov 07 Javascript
js实现敏感词过滤算法及实现逻辑
Jul 24 Javascript
Vue 中axios配置实例详解
Jul 27 Javascript
node中的session的具体使用
Sep 14 Javascript
layui原生表单验证的实例
Sep 09 Javascript
分享一款超好用的JavaScript 打包压缩工具
Apr 26 #Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
Apr 26 #Javascript
javascript 使用sleep函数的常见方法详解
Apr 26 #Javascript
基于JavaScript实现十五拼图代码实例
Apr 26 #Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
Apr 26 #Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
Apr 26 #Javascript
javascript设计模式 ? 访问者模式原理与用法实例分析
Apr 26 #Javascript
You might like
短波收音机简介
2021/03/01 无线电
php中用于检测一个地理IP地址是否可用的代码
2012/02/19 PHP
使用HMAC-SHA1签名方法详解
2013/06/26 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
递归删除一个节点以及该节点下的所有节点示例
2014/03/19 PHP
浅谈PHP错误类型及屏蔽方法
2017/05/27 PHP
Jquery 实现Tab效果 思路是js思路
2010/03/02 Javascript
jquery实现marquee效果(文字或者图片的水平垂直滚动)
2013/01/07 Javascript
jquery自定义滚动条插件示例分享
2014/02/21 Javascript
JavaScript中判断变量是数组、函数或是对象类型的方法
2015/02/25 Javascript
AngularJS中的Directive自定义一个表格
2016/01/25 Javascript
理解javascript定时器中的setTimeout与setInterval
2016/02/23 Javascript
BootStrap Validator使用注意事项(必看篇)
2016/09/28 Javascript
ajax请求data遇到的问题分析
2018/01/18 Javascript
vue打包相关细节整理(小结)
2018/09/28 Javascript
Django模板继承 extend标签实例代码详解
2019/05/16 Javascript
JavaScript实现京东放大镜效果
2019/12/03 Javascript
使用PDB模式调试Python程序介绍
2015/04/05 Python
举例讲解Python设计模式编程中对抽象工厂模式的运用
2016/03/02 Python
Python简单生成随机数的方法示例
2018/03/31 Python
python 多线程对post请求服务器测试并发的方法
2019/06/13 Python
详解Python图像处理库Pillow常用使用方法
2019/09/02 Python
Python 读取 YUV(NV12) 视频文件实例
2019/12/09 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
Python datetime 格式化 明天,昨天实例
2020/03/02 Python
通过python 执行 nohup 不生效的解决
2020/04/16 Python
linux mint中搜狗输入法导致pycharm卡死的问题
2020/10/28 Python
Myprotein加拿大官网:欧洲第一的运动营养品牌
2018/01/06 全球购物
环境工程专业个人求职信
2013/12/05 职场文书
幼儿园老师辞职信
2014/01/20 职场文书
学习十八大报告感言
2014/02/28 职场文书
2015年元旦文艺汇演主持词
2014/03/26 职场文书
党支部组织生活会整改方案
2014/09/30 职场文书
简单实现一个手持弹幕功能+文字抖动特效
2021/03/31 HTML / CSS
python实现批量提取指定文件夹下同类型文件
2021/04/05 Python
浅谈vue2的$refs在vue3组合式API中的替代方法
2021/04/18 Vue.js