原文地址:http://zhangyiheng.com/blog/articles/div_resize.html

需求

开发过程中经常遇到的一个问题就是如何监听一个div的size变化。 
比如我用canvas绘制了一个chart,当canvas的size发生变化的时候,需要重新绘制里面的内容,这个时候就需要监听resize事件做处理。

window上虽然可以添加resize事件监听,但这并不能满足我们的需求,因为很多时候,div的size发生了变化,但是window的size并没有改变。 
不过我们可以间接利用window的resize事件监听来实现对于某个div的resize事件监听,请看下面具体实现。

对于div的resize事件的监听,实现方式有很多,比如周期性检查,通过scroll事件等等,本文主要介绍通过object元素来实现监听。

具体实现

/**
* Created by taozh on 2017/5/6.
* taozh1982@gmail.com
*/
var EleResize = {
_handleResize: function (e) {
var ele = e.target || e.srcElement;
var trigger = ele.__resizeTrigger__;
if (trigger) {
var handlers = trigger.__z_resizeListeners;
if (handlers) {
var size = handlers.length;
for (var i = 0; i < size; i++) {
var h = handlers[i];
var handler = h.handler;
var context = h.context;
handler.apply(context, [e]);
}
}
}
},
_removeHandler: function (ele, handler, context) {
var handlers = ele.__z_resizeListeners;
if (handlers) {
var size = handlers.length;
for (var i = 0; i < size; i++) {
var h = handlers[i];
if (h.handler === handler && h.context === context) {
handlers.splice(i, 1);
return;
}
}
}
},
_createResizeTrigger: function (ele) {
var obj = document.createElement('object');
obj.setAttribute('style',
'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;');
obj.onload = EleResize._handleObjectLoad;
obj.type = 'text/html';
ele.appendChild(obj);
obj.data = 'about:blank';
return obj;
},
_handleObjectLoad: function (evt) {
this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
}
};
if (document.attachEvent) {//ie9-10
EleResize.on = function (ele, handler, context) {
var handlers = ele.__z_resizeListeners;
if (!handlers) {
handlers = [];
ele.__z_resizeListeners = handlers;
ele.__resizeTrigger__ = ele;
ele.attachEvent('onresize', EleResize._handleResize);
}
handlers.push({
handler: handler,
context: context
});
};
EleResize.off = function (ele, handler, context) {
var handlers = ele.__z_resizeListeners;
if (handlers) {
EleResize._removeHandler(ele, handler, context);
if (handlers.length === 0) {
ele.detachEvent('onresize', EleResize._handleResize);
delete ele.__z_resizeListeners;
}
}
}
} else {
EleResize.on = function (ele, handler, context) {
var handlers = ele.__z_resizeListeners;
if (!handlers) {
handlers = [];
ele.__z_resizeListeners = handlers; if (getComputedStyle(ele, null).position === 'static') {
ele.style.position = 'relative';
}
var obj = EleResize._createResizeTrigger(ele);
ele.__resizeTrigger__ = obj;
obj.__resizeElement__ = ele;
}
handlers.push({
handler: handler,
context: context
});
};
EleResize.off = function (ele, handler, context) {
var handlers = ele.__z_resizeListeners;
if (handlers) {
EleResize._removeHandler(ele, handler, context);
if (handlers.length === 0) {
var trigger = ele.__resizeTrigger__;
if (trigger) {
trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
ele.removeChild(trigger);
delete ele.__resizeTrigger__;
}
delete ele.__z_resizeListeners;
}
}
}
}

  

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Resize</title>
<script src="./EleResize.js"></script>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
} #resizeDiv {
width: 60%;
height: 60%;
border: 1px solid red;
margin: 20px;
} button {
margin: 20px 20px 0;
}
</style>
</head>
<body>
<button onclick="addListener()">addListener</button>
<button onclick="removeListener()">removeListener</button>
<button onclick="resize()">resize</button>
<div id="resizeDiv"></div>
<script>
var resizeDiv = document.getElementById('resizeDiv');
function resize() {
resizeDiv.style.width = "200px";
}
var listener = function () {
console.log("resize");
};
function addListener() {
EleResize.on(resizeDiv, listener);
}
function removeListener() {
EleResize.off(resizeDiv, listener)
}
</script>
</body>
</html>

  

原理

这里的具体实现分两类,

  • ie9-10

    默认支持div的resize事件,可以直接通过div.attachEvent('onresize', handler);的方式实现

  • 其它浏览器

    通过在div中添加一个内置object元素实现监听。
    设置object元素的style使其填充满div,这样当div的size发生变化时,object的size也会发生变化。
    然后监听object元素的contentDocument.defaultView(window对象)的resize事件。

注:本文提供的是如何监听resize事件,其实在resize时,可能会连续快速的触发(比如拖动浏览器),为了提高效率,可以考虑使用批处理的模式。

JS监听div的resize事件的更多相关文章

  1. 原生js监听input值改变事件

    哈哈哈,又来了,今天闲来无事,实验了下原生js监听input value值改变事件,下面就来说道说道: 本来写监听input值便获是用jquery的,之前的随笔写了,就是这个方法,地址:http:// ...

  2. ActiveX(二)Js 监听 ActiveX中的事件

    在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...

  3. FineReport——JS监听其他控件事件

    首先在参数面板和报表中分布添加一个button,用于被监听: 参数面板 控件名:temp: temp点击事件:alert("temp"); 报表 控件名:exprt: temp点击 ...

  4. js监听页面的scroll事件,当移到底部时触发事件

    //页面拉到底时自动加载更多 $(window).scroll(function(event){ var wScrollY = window.scrollY; // 当前滚动条位置 var wInne ...

  5. js监听文本框变化事件

    用js有两种写法: 法一: <!DOCTYPE HTMl> <html> <head> <title> new document </title& ...

  6. JS 监听绑定和取消事件

    1. 原生 JS 语言: 绑定:addEventListener(type, function, false) 取消: removeEventListener(type, function, fals ...

  7. js监听全屏的事件

    window.addEventListener('click',function(){ window.top.location.href = '../../loginOut.do';  //解决ifr ...

  8. js监听 window.open 关闭事件

    转载自:http://blog.csdn.net/hanshileiai/article/details/41346729 首先创建一个新的对象,这将打开一个弹出这样的: var winObj = w ...

  9. js 监听整个页面的回车事件

    JS监听整个页面的回车事件 <script type="text/javascript"> document.onkeydown=keyDownSearch;      ...

随机推荐

  1. JDK版本不匹配...

    Java compiler level does not match the version of the installed Java project facet. 今天从把交通厅的项目,导进来就报 ...

  2. eclipse--java工程转web工程 以及 java或java web工程转maven工程

    1.  打开工程文件夹,编辑工程的.project文件. 在<natures></natures>中加入 <nature>org.eclipse.wst.commo ...

  3. python课程day_2-->总结-->字符串功能

    =======================课程大纲=======================> 基本数据类型 - 整数 - 布尔值 - 字符串 - 列表 - 元组 - 字典 - 集合 工 ...

  4. JavaScript算法 ,Python算法,Go算法,java算法,系列之【归并排序】篇

    常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等.用一张图概括: 归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的 ...

  5. Linux中Nginx反向代理下的tomcat集群

    Nginx具有反向代理(注意和正向代码的区别)和负载均衡等特点. 这次Nginx安装在 192.168.1.108 这台linux 机器上.安装Nginx 先要装openssl库,gcc,PCRE,z ...

  6. Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue

    功能简介: ArrayBlockingQueue是一种基于数组实现的有界的阻塞队列.队列中的元素遵循先入先出(FIFO)的规则.新元素插入到队列的尾部,从队列头部取出元素. 和普通队列有所不同,该队列 ...

  7. 合成(composite)模式

    合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述整体与部分的关系.合成模式可以使客户端将单纯元素与复合元素同等看待. 合成模式 合成模式把部分和整 ...

  8. 使用java对文件批量重命名

    有时候从网络上下载的电视剧或者动漫,名字上都会被该网站加上前缀或者后缀,如图: 那么处女座的同学就不同意了,不行,我就是想让它按照我的习惯方式命名!但是呢,一个个修改是不是特别麻烦,如果是上百个呢?如 ...

  9. 解决Windos7中优盘安装centos7后无法引导原系统问题

    一前言 最近学习Linux操作系统,打算在原Window7系统中装centOS7系统,使笔记本上跑双系统.将系统D盘的文件转移后,删除卷标,将U盘做成CentOS7启动盘,进行正常安装.此为前提. 但 ...

  10. MyBatis之级联——鉴别器

    鉴别器(discriminator)是MyBatis为我们提供的第三个级联也是最后一个.基于之前两篇级联中的场景,现增加学生们去体检,但男女体检项目不一样,我们把男女体检表做成两张表,当然我想也可以设 ...