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 相关文章推荐
js将当前时间格式转换成时间搓(自写)
Sep 26 Javascript
javascript的回调函数应用示例
Feb 20 Javascript
javaScript年份下拉列表框内容为当前年份及前后50年
May 28 Javascript
使用javascript获取页面名称
Dec 23 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
整理关于Bootstrap表单的慕课笔记
Mar 29 Javascript
JS实现弹出下载对话框及常见文件类型的下载
Jul 13 Javascript
node.js中使用Export和Import的方法
Sep 18 Javascript
Vue 使用计时器实现跑马灯效果的实例代码
Jul 11 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
Sep 17 Javascript
JavaScript经典案例之简易计算器
Aug 24 Javascript
vue+openlayers绘制省市边界线
Dec 24 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
mysql 搜索之简单应用
2007/04/27 PHP
写php分页时出现的Fatal error的解决方法
2011/04/18 PHP
PHP下打开phpMyAdmin出现403错误的问题解决方法
2013/05/23 PHP
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
PJBlog插件 防刷新的在线播放器
2006/10/25 Javascript
DOM下的节点属性和操作小结
2009/05/14 Javascript
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
鼠标经过显示二级菜单js特效
2013/08/13 Javascript
JavaScript利用正则表达式去除日期中的“-”
2014/07/01 Javascript
jquery表单验证插件(jquery.validate.js)的3种使用方式
2015/03/28 Javascript
JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同
2015/11/15 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
2016/01/26 Javascript
AngularJS  ng-table插件设置排序
2016/09/21 Javascript
基于Vue实现拖拽效果
2018/04/27 Javascript
Cordova(ionic)项目实现双击返回键退出应用
2019/09/17 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
2019/09/25 Javascript
微信小程序(订阅消息)功能
2019/10/25 Javascript
jQuery实现的上拉刷新功能组件示例
2020/05/01 jQuery
JS实现拖动模糊框特效
2020/08/25 Javascript
[40:50]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第四场
2014/05/24 DOTA
python中mechanize库的简单使用示例
2014/01/10 Python
为Python程序添加图形化界面的教程
2015/04/29 Python
在Ubuntu系统下安装使用Python的GUI工具wxPython
2016/02/18 Python
Python面向对象程序设计示例小结
2019/01/30 Python
python 字典操作提取key,value的方法
2019/06/26 Python
django自带调试服务器的使用详解
2019/08/29 Python
Python queue队列原理与应用案例分析
2019/09/27 Python
python爬虫爬取笔趣网小说网站过程图解
2019/11/18 Python
python使用QQ邮箱实现自动发送邮件
2020/06/22 Python
解决PyCharm IDE环境下,执行unittest不生成测试报告的问题
2020/09/03 Python
党校培训自我鉴定
2014/02/01 职场文书
小班开学寄语
2014/04/04 职场文书
检讨书范文1000字
2015/01/28 职场文书
2015年置业顾问工作总结
2015/04/07 职场文书
导游词之苏州阳澄湖
2019/11/15 职场文书
SQL SERVER中常用日期函数的具体使用
2021/04/08 SQL Server