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 打地鼠游戏代码说明
Oct 12 Javascript
一个JavaScript函数把URL参数解析成Json对象
Sep 24 Javascript
js时间日期格式化封装函数
Dec 02 Javascript
JS实现在线统计一个页面内鼠标点击次数的方法
Feb 28 Javascript
JavaScript中定义函数的三种方法
Mar 12 Javascript
浅谈JSON.parse()和JSON.stringify()
Jul 14 Javascript
HTML5 canvas 9绘制图片实例详解
Sep 06 Javascript
vue中component组件的props使用详解
Sep 04 Javascript
Vue 使用中的小技巧
Apr 26 Javascript
微信小程序scroll-view点击项自动居中效果的实现
Mar 25 Javascript
小谈angular ng deploy的实现
Apr 07 Javascript
js基于div丝滑实现贝塞尔曲线
Sep 23 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读取二进制流(C语言结构体struct数据文件)的深入解析
2013/06/13 PHP
PHP使用正则表达式清除超链接文本
2013/11/12 PHP
Laravel 5框架学习之子视图和表单复用
2015/04/09 PHP
微信自定义菜单的处理开发示例
2015/04/16 PHP
php结合redis高并发下发帖、发微博的实现方法
2016/12/15 PHP
Laravel等框架模型关联的可用性浅析
2019/12/15 PHP
网站上面有这种切换效果
2006/06/26 Javascript
用JavaScript编写COM组件的步骤
2009/03/17 Javascript
JavaScript 页面坐标相关知识整理
2010/01/09 Javascript
常见效果实现之返回顶部(结合淡入、淡出、减速滚动)
2012/01/04 Javascript
js带缩略图的图片轮播效果代码分享
2015/09/14 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
2015/12/10 Javascript
利用jquery实现实时更新歌词的方法
2017/01/06 Javascript
vue表单绑定实现多选框和下拉列表的实例
2017/08/12 Javascript
Vue.js划分组件的方法
2017/10/29 Javascript
基于vue 实现token验证的实例代码
2017/12/14 Javascript
Vue用v-for给src属性赋值的方法
2018/03/03 Javascript
layUI实现三级导航菜单效果
2019/07/26 Javascript
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
JavaScript获取当前url路径过程解析
2019/12/27 Javascript
Node.js+Vue脚手架环境搭建的方法步骤
2020/03/08 Javascript
Python中的自定义函数学习笔记
2014/09/23 Python
Python isinstance函数介绍
2015/04/14 Python
简单讲解Python中的数字类型及基本的数学计算
2016/03/11 Python
Python实现登录接口的示例代码
2017/07/21 Python
flask框架使用orm连接数据库的方法示例
2018/07/16 Python
python实现彩票系统
2020/06/28 Python
如何配置关联Python 解释器 Anaconda的教程(图解)
2020/04/30 Python
python输入中文的实例方法
2020/09/14 Python
python字典按照value排序方法
2020/12/28 Python
加拿大最大的体育用品、鞋类和服装零售商:Sport Chek
2018/11/29 全球购物
T3官网:头发造型工具
2019/12/26 全球购物
会议欢迎标语
2014/06/30 职场文书
勇敢的心观后感
2015/06/09 职场文书
飞越疯人院观后感
2015/06/09 职场文书
只用Python就可以制作的简单词云
2021/06/07 Python