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中的Split使用方法与技巧
Mar 09 Javascript
javascript下IE与FF兼容函数收集
Sep 17 Javascript
JS 文字符串转换unicode编码函数
May 30 Javascript
JQuyer $.post 与 $.ajax 访问WCF ajax service 时的问题需要注意的地方
Sep 20 Javascript
js获取上传文件大小示例代码
Apr 10 Javascript
angularJS 入门基础
Feb 09 Javascript
js中日期的加减法
May 06 Javascript
js实现简单排列组合的方法
Jan 27 Javascript
JavaScript 对象详细整理总结
Sep 29 Javascript
JavaScript使用简单正则表达式的数据验证功能示例
Jan 13 Javascript
js get和post请求实现代码解析
Feb 06 Javascript
Vue父组件向子组件传值以及data和props的区别详解
Mar 02 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
php 中的4种标记风格介绍
2012/05/10 PHP
PHP实现模仿socket请求返回页面的方法
2014/11/04 PHP
php curl抓取网页的介绍和推广及使用CURL抓取淘宝页面集成方法
2015/11/30 PHP
composer.lock文件的作用
2016/02/03 PHP
THREE.JS入门教程(5)你应当知道的十件事
2013/01/24 Javascript
JavaScript正则表达式之multiline属性的应用
2015/06/16 Javascript
Jquery实现瀑布流布局(备有详细注释)
2015/07/31 Javascript
jQuery实现文本框邮箱输入自动补全效果
2015/11/17 Javascript
jquery仿QQ登录账号选择下拉框效果
2016/03/22 Javascript
使用jQuery5分钟快速搞定双色表格的简单实例
2016/08/08 Javascript
jQuery的ajax中使用FormData实现页面无刷新上传功能
2017/01/16 Javascript
基于JavaScript实现焦点图轮播效果
2017/03/27 Javascript
详解从Vue-router到html5的pushState
2018/07/21 Javascript
JS封装的模仿qq右下角消息弹窗功能示例
2018/08/22 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
JS实现图片轮播效果实例详解【可自动和手动】
2019/04/04 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
2019/04/26 Javascript
angular4+百分比进度显示插件用法示例
2019/05/05 Javascript
原生js实现each方法实例代码详解
2019/05/27 Javascript
js判断复选框是否选中的方法示例【基于jQuery】
2019/10/10 jQuery
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
python单线程实现多个定时器示例
2014/03/30 Python
用Python代码来解图片迷宫的方法整理
2015/04/02 Python
Python2.7简单连接与操作MySQL的方法
2016/04/27 Python
Python基于Matplotlib库简单绘制折线图的方法示例
2017/08/14 Python
python处理csv数据动态显示曲线实例代码
2018/01/23 Python
Python中一行和多行import模块问题
2018/04/01 Python
python中scrapy处理项目数据的实例分析
2020/11/22 Python
Html5 滚动穿透的方法
2019/05/13 HTML / CSS
期末考试动员演讲稿
2014/01/10 职场文书
优秀老员工获奖感言
2014/02/15 职场文书
英文自荐信范文
2015/03/25 职场文书
计划生育目标责任书
2015/05/09 职场文书
如何写好活动总结
2019/06/21 职场文书
2019通用版劳动合同范本!
2019/07/11 职场文书
springboot如何接收application/x-www-form-urlencoded类型的请求
2021/11/02 Java/Android