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的标签智能验证实现代码
Dec 27 Javascript
在浏览器中获取当前执行的脚本文件名的代码
Jul 19 Javascript
jquery获取tagName再进行判断
May 29 Javascript
Egret引擎开发指南之视觉编程
Sep 03 Javascript
firefox浏览器用jquery.uploadify插件上传时报HTTP 302错误
Mar 01 Javascript
jQuery实现将div中滚动条滚动到指定位置的方法
Aug 10 Javascript
jquery对Json的各种遍历方法总结(必看篇)
Sep 29 Javascript
JavaScript引用类型RegExp基本用法详解
Aug 09 Javascript
javascript设计模式 ? 组合模式原理与应用实例分析
Apr 14 Javascript
uniapp实现横向滚动选择日期
Oct 21 Javascript
antd Select下拉菜单动态添加option里的内容操作
Nov 02 Javascript
uniapp 微信小程序 自定义tabBar 导航
Apr 22 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 getimagesize 上传图片的长度和宽度检测代码
2010/05/15 PHP
php数组函数序列之prev() - 移动数组内部指针到上一个元素的位置,并返回该元素值
2011/10/31 PHP
ThinkPHP框架设计及扩展详解
2014/11/25 PHP
PHP文件缓存类实现代码
2015/10/26 PHP
深入理解PHP 数组之count 函数
2016/06/13 PHP
PHP实现图片批量打包下载功能
2017/03/01 PHP
PHP中ltrim()函数的用法与实例讲解
2019/03/28 PHP
看了就知道什么是JSON
2007/12/09 Javascript
跨域请求之jQuery的ajax jsonp的使用解惑
2011/10/09 Javascript
js string 转 int 注意的问题小结
2013/08/15 Javascript
js获取和设置属性的方法
2014/02/20 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
基于JavaScript实现轮播图代码
2016/07/14 Javascript
JavaScript  event对象整理及详细介绍
2016/10/10 Javascript
探究Vue.js 2.0新增的虚拟DOM
2016/10/20 Javascript
js从输入框读取内容,比较两个数字的大小方法
2017/03/13 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
nodejs socket服务端和客户端简单通信功能
2017/09/14 NodeJs
在vue-cli中组件通信的方法
2017/12/16 Javascript
详解webpack之图片引入-增强的file-loader:url-loader
2018/10/08 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
vscode中Vue别名路径提示的实现
2020/07/31 Javascript
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
python变量不能以数字打头详解
2016/07/06 Python
numpy中的高维数组转置实例
2018/04/17 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
Python 使用 prettytable 库打印表格美化输出功能
2019/12/26 Python
Python 如何测试文件是否存在
2020/07/31 Python
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
需求分析说明书
2014/05/09 职场文书
党支部三会一课计划
2014/09/24 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
2014年加油站站长工作总结
2014/12/23 职场文书
导游词之徐州云龙湖
2019/11/19 职场文书
Django使用echarts进行可视化展示的实践
2021/06/10 Python