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 获取网页参数系统
Jul 19 Javascript
JavaScript实现动态增加文件域表单
Feb 12 Javascript
js实时监听文本框状态的方法
Apr 26 Javascript
JS Date函数整理方便使用
Oct 23 Javascript
javascript客户端遍历控件与获取父容器对象示例代码
Jan 06 Javascript
JavaScript中5种调用函数的方法
Mar 12 Javascript
jquery实现二级导航下拉菜单效果
Dec 18 Javascript
jquery仿QQ登录账号选择下拉框效果
Mar 22 Javascript
jQuery如何获取动态添加的元素
Jun 24 Javascript
原生JS实现图片网格式渐显、渐隐效果
Jun 05 Javascript
使用JavaScript实现链表的数据结构的代码
Aug 02 Javascript
JS二级菜单不同实现方法分析【4种方法】
Dec 21 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读取目录及子目录下所有文件名的方法
2014/10/20 PHP
用PHP代码给图片加水印
2015/07/01 PHP
php实现可运算的验证码
2015/11/10 PHP
Ubuntu上安装yaf扩展的方法
2018/01/29 PHP
one.php 多项目、函数库、类库 统一为一个版本的方法
2020/08/24 PHP
JavaScript 动态加载脚本和样式的方法
2015/04/13 Javascript
Jquery基础之事件操作详解
2016/06/14 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
2016/08/25 Javascript
Bootstrap框架的学习教程详解(二)
2016/10/18 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
JavaScript数组去重的6个方法
2017/01/21 Javascript
Vue路由跳转问题记录详解
2017/06/15 Javascript
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
2018/05/16 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
2018/07/02 Javascript
开发用到的js封装方法(20种)
2018/10/12 Javascript
微信小程序:数据存储、传值、取值详解
2019/05/07 Javascript
微信小程序 scroll-view 实现锚点跳转功能
2019/12/12 Javascript
js实现轮播图特效
2020/05/28 Javascript
WebStorm无法正确识别Vue3组合式API的解决方案
2021/02/18 Vue.js
python中list列表的高级函数
2016/05/17 Python
Python从零开始创建区块链
2018/03/06 Python
基于python的多进程共享变量正确打开方式
2018/04/28 Python
Python实现决策树并且使用Graphviz可视化的例子
2019/08/09 Python
Python爬虫如何破解JS加密的Cookie
2020/11/19 Python
python爬虫线程池案例详解(梨视频短视频爬取)
2021/02/20 Python
戴尔加拿大官网:Dell加拿大
2016/09/17 全球购物
Charles&Keith美国官方网站:新加坡快时尚鞋类和配饰零售商
2019/11/27 全球购物
英国领先的高级美容和在线皮肤诊所:Face the Future
2020/06/17 全球购物
继电保护工岗位职责
2014/01/05 职场文书
反对四风问题自我剖析材料
2014/09/29 职场文书
离婚财产分隔协议书
2014/10/23 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
Python中os模块的简单使用及重命名操作
2021/04/17 Python
CSS3新特性详解(五):多列columns column-count和flex布局
2021/04/30 HTML / CSS
iSCSI服务器CHAP双向认证配置
2022/04/01 Servers