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 相关文章推荐
javascript实现的网页局布刷新效果
Dec 01 Javascript
分享一个自定义的console类 让你不再纠结JS中的调试代码的兼容
Apr 20 Javascript
APP中javascript+css3实现下拉刷新效果
Jan 27 Javascript
jquery自定义插件——window的实现【示例代码】
May 06 Javascript
JavaScript调试的多个必备小Tips
Jan 15 Javascript
swiper.js插件实现pc端文本上下滑动功能示例
Dec 03 Javascript
jsonp实现百度下拉框功能的方法分析
May 10 Javascript
模块化react-router配置方法详解
Jun 03 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 Javascript
vue移动端模态框(可传参)的实现
Nov 20 Javascript
Vue实现购物小球抛物线的方法实例
Nov 22 Vue.js
vue实现Toast组件轻提示
Apr 10 Vue.js
分享一款超好用的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
Zend Framework框架之Zend_Mail实现发送Email邮件验证功能及解决标题乱码的方法
2016/03/21 PHP
ExtJS 2.0实用简明教程 之Ext类库简介
2009/04/29 Javascript
json格式化/压缩工具 Chrome插件扩展版
2010/05/25 Javascript
Jquery事件的连接使用示例
2013/06/18 Javascript
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
禁用Enter键表单自动提交实现代码
2014/05/22 Javascript
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
javascript从作用域链谈闭包
2020/07/29 Javascript
JavaScript实现数据类型的相互转换
2016/03/06 Javascript
用JS动态设置CSS样式常见方法小结(推荐)
2016/11/10 Javascript
jquery仿ps颜色拾取功能
2017/03/08 Javascript
详解weex默认webpack.config.js改造
2018/01/08 Javascript
微信小程序数字滚动插件使用详解
2018/02/02 Javascript
JS多个异步请求 按顺序执行next实现解析
2019/09/16 Javascript
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
2019/10/11 Javascript
python用ConfigObj读写配置文件的实现代码
2013/03/04 Python
Python二分法搜索算法实例分析
2015/05/11 Python
python中input()与raw_input()的区别分析
2016/02/27 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
PyCharm 设置SciView工具窗口的方法
2019/01/15 Python
对python函数签名的方法详解
2019/01/22 Python
python set内置函数的具体使用
2019/07/02 Python
画pytorch模型图,以及参数计算的方法
2019/08/17 Python
Python基于read(size)方法读取超大文件
2020/03/12 Python
python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
2020/04/07 Python
Grid 宫格常用布局的实现
2020/01/10 HTML / CSS
可打印的优惠券、杂货和优惠券代码:Coupons.com
2018/06/12 全球购物
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
Java Servlet API中forward() 与redirect()的区别
2014/04/20 面试题
2014年大学生党员评议表自我评价
2014/09/20 职场文书
不尊敬老师检讨书范文
2014/11/19 职场文书
2015年高三年级组工作总结
2015/07/21 职场文书
2016教师给学生的毕业寄语
2015/12/04 职场文书
简历自我评价:教师师德表现自我评价
2019/04/24 职场文书
Python django中如何使用restful框架
2021/06/23 Python
python中的getter与setter你了解吗
2022/03/24 Python