js监听div元素的宽高变化

36次阅读

共计 2840 个字符,预计需要花费 8 分钟才能阅读完成。

一、js 监听 window 变化的方法

1、onsize 只能监听 window 对象的变化

(1)、window 对象原生、jQuery 方法

// 原生写法
window.onsize = function(){console.log("11");
}

//jquery 写法
$(window).resize(function(){console.log("22");
})

// 注意:浏览器窗口大小改变时,这段代码会执行多次,对性能影响大,容易造成浏览器假死。

(2)、实现不管窗口怎么改变,只在停止改变之后才执行代码

var resizeTimer = null;

$(window).resize(function(){if(resizeTimer){clearTimeout(resizeTimer);
    }
    resizeTimer = setTimeout(function(){console.log("窗口改变")
    },100)
})

// 通过使用定时器的方式来让代码延迟执行,每次窗口改变的时候就清除事件,只有停下改变之后才会继续再执行,解决 resize 执行多次的问题。

二、js 监听 div 容器变化的方法

1、MutationObserver

(1)、介绍:MutationObserver 可以用来监听整个 DOM 中的变化

(2)、构造函数,参数为回调函数

构造函数为 window.MutationObserver,它在监听到 DOM 中的改变并且一系列改变结束后触发回调函数。他与事件不同的是:它在 DOM 变化时,会记录每一个 DOM 的变化(为一个 MutationRecord 对象),到 DOM 变化结束时触发回调函数。DOM 变化可能是一系列的(比如同时改变宽和高),那么这一系列的变化就会产生一个队列,这个队列会作为参数传递给回调函数。

由于浏览器差异。一些版本的浏览器各自支持了构造函数,但是用法一致的。实例化一个观察者,代码如下:

let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
let observer = new MutationObserver(callback);

(3)、常用三个 API 接口

1️⃣、observe(element,options) 配置 MutationObserver 在 DOM 更改匹配给定选项时,通过其回调函数开始接收通知。
element 是要监听的 DOM 元素,options 为监听选项对象,可选的选项如下:

所以监听元素宽高变化,就是监听 style 属性变化


observer.observe(element,{attributes:true,attributeFilter:['style'],attributeOldValue:true});

// 这样当元素 style 发生变化时,就会触发构造函数中的 callback 函数。即:let observer = new MutationObserver(callback),触发这里的 callback。

2️⃣、disconnect()  阻止 MutationObserver 实例继续接收的通知,直到再次调用其 observe 方法,该观察者对象包含的回调函数都不会再被调用。

3️⃣、takeRecords() 从 MutationObserver 的通知队列中删除所有待处理的通知,并将它们返回到一个 MutationRecord 对象构成的新数组中。

2、vue 示例

<template>
  <div class="container">
    <div class="resize-element">
      改变大小试试
    </div>
    <div class="resize-record">
      触发了 {{firedNum}} 次 resize 事件。</div>
  </div>
</template>
 
<script>
export default {
  showName: '监听 DOM 变化',
  data () {
    return {
      observer: null,
      firedNum: 0,
      recordOldValue: { // 记录下旧的宽高数据,避免重复触发回调函数
        width: '0',
        height: '0'
      }
    }
  },
  mounted () {
    let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
    let element = document.querySelector('.resize-element')
    this.observer = new MutationObserver((mutationList) => {for (let mutation of mutationList) {console.log(mutation)
      }
      let width = getComputedStyle(element).getPropertyValue('width')
      let height = getComputedStyle(element).getPropertyValue('height')
      if (width === this.recordOldValue.width && height === this.recordOldValue.height) return
      this.recordOldValue = {
        width,
        height
      }
      this.firedNum += 1
    })
    this.observer.observe(element, { attributes: true, attributeFilter: ['style'], attributeOldValue: true })
  },
  beforeDestroyed () {if (this.observer) {this.observer.disconnect()
      this.observer.takeRecords()
      this.observer = null
    }
  }
}
</script>
 
<style lang="stylus" scoped>
.container
  position relative
  .resize-element
    transform translate(-50%, -50%)
    position absolute
    top 50%
    left 50%
    height 10rem
    width 10rem
    overflow hidden
    resize both
    display block
    box-shadow 0 0 1px 1px #3361D8
    border-radius 2px
</style>

注意:这里记录了旧的宽高数据来避免重复触发回调函数,这样做的原因在于宽高数据改变时,不一定是整数,而 MutationRecord.recordOldValue 中记录的是取整后的数据,这样就会导致在拖动改变 DOM 元素的宽高时,数值一直在整数和小数之间跳动,会多次触发。

正文完
 0