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 简单验证代码(用户名,密码,邮箱)
Sep 28 Javascript
utf-8编码引起js输出中文乱码的解决办法
Jun 23 Javascript
dojo随手记 gird组件引用
Feb 24 Javascript
ES6中箭头函数的定义与调用方式详解
Jun 02 Javascript
Bootstrap与Angularjs的模态框实例代码
Aug 03 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
微信小程序图片轮播组件gallery slider使用方法详解
Jan 31 Javascript
详解vue配置后台接口方式
Mar 29 Javascript
微信小程序搭建自己的Https服务器
May 02 Javascript
ajax跨域访问遇到的问题及解决方案
May 23 Javascript
vue自定义指令限制输入框输入值的步骤与完整代码
Aug 30 Javascript
Vue实现跑马灯样式文字横向滚动
Nov 23 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
php查找字符串出现次数的方法
2014/12/01 PHP
php实现搜索类封装示例
2016/03/31 PHP
Yii2 rbac权限控制操作步骤实例教程
2016/04/29 PHP
Laravel如何实现适合Api的异常处理响应格式
2020/06/14 PHP
js分解url参数(面向对象-极简主义法应用)
2012/08/09 Javascript
Jquery原生态实现表格header头随滚动条滚动而滚动
2014/03/18 Javascript
移动端JQ插件hammer使用详解
2015/07/03 Javascript
基于jQuery实现简单的折叠菜单效果
2015/11/23 Javascript
关于网页中的无缝滚动的js代码
2016/06/09 Javascript
jquery实现的回旋滚动效果完整实例【附demo源码下载】
2016/09/20 Javascript
JS用斜率判断鼠标进入DIV四个方向的方法
2016/11/07 Javascript
angularjs使用directive实现分页组件的示例
2017/02/07 Javascript
nodejs个人博客开发第四步 数据模型
2017/04/12 NodeJs
JS实现点击循环切换显示内容的方法
2017/10/19 Javascript
从vue基础开始创建一个简单的增删改查的实例代码(推荐)
2018/02/11 Javascript
Javascript实现异步编程的过程
2018/06/18 Javascript
js实现时分秒倒计时
2019/12/03 Javascript
vue引用外部JS的两种种方法
2020/01/28 Javascript
vue.js 输入框输入值自动过滤特殊字符替换中问标点操作
2020/08/31 Javascript
JavaScript setTimeout()基本用法有哪些
2020/11/04 Javascript
python迭代器的使用方法实例
2013/11/21 Python
Python实现的多进程和多线程功能示例
2018/05/29 Python
pandas分别写入excel的不同sheet方法
2018/12/11 Python
详解python调用cmd命令三种方法
2019/07/08 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
2019/07/11 Python
解决Python3 控制台输出InsecureRequestWarning问题
2019/07/15 Python
python实现Pyecharts实现动态地图(Map、Geo)
2020/03/25 Python
python百行代码自制电脑端网速悬浮窗的实现
2020/05/12 Python
网络通讯中,端口有什么含义,端口的取值范围
2012/11/23 面试题
医生进修自我鉴定
2014/01/19 职场文书
主题教育活动总结
2014/05/05 职场文书
六年级学生评语大全
2014/12/26 职场文书
vue3获取当前路由地址
2022/02/18 Vue.js
css3带你实现3D转换效果
2022/02/24 HTML / CSS
pd.DataFrame中的几种索引变换的实现
2022/06/16 Python
Python如何加载模型并查看网络
2022/07/15 Python