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 document.compatMode兼容性
Feb 23 Javascript
js去除输入框中所有的空格和禁止输入空格的方法
Jun 09 Javascript
jquery实现滑动特效代码
Aug 10 Javascript
Node.js数据库操作之连接MySQL数据库(一)
Mar 04 Javascript
jQuery实现拼图小游戏(实例讲解)
Jul 24 jQuery
浅谈Vuejs Prop基本用法
Aug 17 Javascript
探索Vue高阶组件的使用
Jan 08 Javascript
JavaScript实现动态添加、移除元素或属性的方法分析
Jan 03 Javascript
VUE引入第三方js包及调用方法讲解
Mar 01 Javascript
了解重排与重绘
May 29 Javascript
vuejs+element UI table表格中实现禁用部分复选框的方法
Sep 20 Javascript
jQuery实现购物车全功能
Jan 11 jQuery
分享一款超好用的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实现批量压缩图片文件大小的脚本
2014/07/04 PHP
Mac OS下配置PHP+MySql环境
2015/02/25 PHP
php魔术方法功能与用法实例分析
2016/10/19 PHP
利用laravel搭建一个迷你博客实战教程
2017/08/13 PHP
ThinkPHP5.1框架页面跳转及修改跳转页面模版示例
2019/05/06 PHP
Yii Framework框架开发微信公众平台示例
2020/04/26 PHP
a标签的css样式四个状态
2021/03/09 HTML / CSS
基于jquery的inputlimiter 实现字数限制功能
2010/05/30 Javascript
浅析Cookie中的Path与domain
2013/12/18 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
js实现对table的增加行和删除行的操作方法
2016/10/13 Javascript
详解AngularJS ui-sref的简单使用
2017/04/24 Javascript
vue移动端实现红包雨效果
2020/06/23 Javascript
解决layui中的form表单与button的点击事件冲突问题
2018/08/15 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
2020/09/24 Javascript
Python实现豆瓣图片下载的方法
2015/05/25 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
python urllib urlopen()对象方法/代理的补充说明
2017/06/29 Python
对pandas中apply函数的用法详解
2018/04/10 Python
符合语言习惯的 Python 优雅编程技巧【推荐】
2018/09/25 Python
Python嵌套式数据结构实例浅析
2019/03/05 Python
Python socket模块实现的udp通信功能示例
2019/04/10 Python
Python Django框架单元测试之文件上传测试示例
2019/05/17 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
全面解析HTML5中的标准属性与自定义属性
2016/02/18 HTML / CSS
eBay德国站:eBay.de
2017/09/14 全球购物
司法所长先进事迹
2014/06/02 职场文书
医院义诊活动总结
2014/07/04 职场文书
英语四级考试作弊检讨书
2014/09/29 职场文书
2015年幼儿园新年寄语
2014/12/08 职场文书
自主招生专家推荐信
2015/03/26 职场文书
学生会生活部工作总结2015
2015/03/31 职场文书
生产实习心得体会范文
2016/01/22 职场文书
nginx配置ssl实现https的方法示例
2021/03/31 Servers
使用MybatisPlus打印sql语句
2022/04/22 SQL Server