web开发过程中为了更好的实现元素自适应效果,往往需要监听DIV的尺寸变化。而DIV元素不像window对象,是没有resize事件的,我们无法直接监听DIV的resize事件。因此在需要对DIV元素进行监听时,需要采用一些特定方法完成size的监听。

方法1: 嵌入iframe方案

        由于iframe元素包含一个window对象,我们可以在要监听的div元素上嵌入一个iframe元素,使其高度和宽度设置为100%,将DIV元素撑满,当DIV尺寸变化时,iframe也会随之变化,我们可以通过监听iframe的resize事件完成间接对DIV元素尺寸变化的监听。

        由此思路编辑js文件如下:

(function () {
    var 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
    }

    /**
     * 初始化对象,创建iframe并绑定其window的resize
     * 
     */
    ElementResize.prototype.__init = function () {
      var 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,
        position: "absolute",
        left: 0,
        top: 0,
        width: "100%",
        height: "100%",
        "z-index": "-999",
      };
      var styleText = "";
      for (key in styleJson) {
        styleText += key + ":" + styleJson[key] + ";";
      }
      el.style.cssText = styleText;
    };

    /**
     * 创建元素
     * @param {Object} style
     */
    ElementResize.prototype.crateIElement = function (style) {
      var 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 () {
      var 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);
    };
    /**
     * 解除监听
     * 
     */
     ElementResize.prototype.unListen = function () {
        this.queue = [];
      };

    self.ElementResize = ElementResize;
  })();

该文件构建了一个ElementResize构造方法,通过实例化该构造方法创建出监听实例,将该文件引入文件,使用方法如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>DIV尺寸监听</title>
	<script src="./divResizeObserver.js"></script>
  </head>
  <body>
	<button onclick="listenResize()">监听变化</button>
	<button onclick="unListenResize()">解除监听</button>
	<button onclick="changeSize()">改变尺寸</button>
    <div id="content">
     div尺寸变更监听
    </div>
    <script type="text/javascript">
		var eleResize = new ElementResize("#content");
		//执行监听
		function listenResize(){
			eleResize.listen(function () {
				console.count("listener1触发");
			});
			eleResize.listen(function () {
				console.count('listener2触发');
			});
		}
		//监听调用
		listenResize();

		//解除监听
		function unListenResize(){
			eleResize.unListen();
		}
      //宽高变化
		function changeSize(){
			var el = document.querySelector("#content");
			el.style.width = Math.floor(Math.random() * 900) + "px";
			el.style.height = Math.floor(Math.random() * 500) + "px";
		}
    </script>
	 <style type="text/css">
		#content {
		  background:blue;
		  max-width: 100%;
		  max-height: 100%;
		  overflow: auto;
		  text-align:center;
		}
		html,
		body {
		  height: 100%;
		  width: 100%;
		  margin:0;
		}
	  </style>
  </body>
</html>

效果如下:

 方案2  ResizeObserver

    ResizeObserver 接口可以监听到 Element 的内容区域或 SVGElement的边界框改变。

该对象提供三种方法:

ResizeObserver.disconnect()https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver/disconnect

        取消和结束目标对象上所有对 ElementSVGElement 观察。

ResizeObserver.observe()https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver/observe

        开始观察指定的 ElementSVGElement

ResizeObserver.unobserve()https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver/unobserve

        结束观察指定的ElementSVGElement

使用方式也很简单:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="change()">更改</button>   
    <div id="test" class="test" >

    </div>
    <script>
        function change(){
            let el = document.querySelector('#test');
           // el.style.width =Math.floor(Math.random()* 1000) + 'px';
            el.style.height =Math.floor(Math.random() * 1000 ) + 'px';
        }
        window.onload = function(){
           // 尺寸监听
            const resizeObserver = new ResizeObserver(entries => {
                console.count("resize变化啦");
            });
            const someEl = document.querySelector('#test');
            resizeObserver.observe(someEl);

        }
    </script>

    <style>
        .test{
            width:100%;
            height:100%;
            min-height:100px;
            background:red
        }
    </style>
</body>
</html>

 效果:

         该对象的方法使用非常方便,缺点是浏览器兼容性不好:

        那是不是就不能使用了呢,我们可以使用一个github上的ResizeObserver Polyfill。

安装:

npm install resize-observer-polyfill --save-dev

 使用方式:



import ResizeObserver from 'resize-observer-polyfill';
 
const ro = new ResizeObserver((entries, observer) => {
    for (const entry of entries) {
        const {left, top, width, height} = entry.contentRect;
 
        console.log('Element:', entry.target);
        console.log(`Element's size: ${ width }px x ${ height }px`);
        console.log(`Element's paddings: ${ top }px ; ${ left }px`);
    }
});
 
ro.observe(document.body);

最后,更多内容欢迎小伙伴关注:

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐