window.onresize 无效(window.onresize的详细使用)
最近做的项目老是涉及到大小屏切换 ,但是因为屏幕宽高不一样的原因 ,老是要计算表格高度
window.onresize:监听window窗口变化 ,当窗口大小发生变化时 ,会触发此事件
含义
MDN中的定义是这样子的:
文档视图调整大小时会触发 resize事件 。
在js中使用
window.onresize = function(){ // todo event }在html中使用
<body onresize="myFunction()">在vue中的使用
需要注意的是 ,this在函数中指的是window ,而不是vue实例
mounted(){ const _this = this window.onresize = function(){ _this.width = document.body.clientWidth // todo event } }需要注意的两点:
1 、this在函数中不可用 ,他在函数中不一定指全局上下文
解决办法如下:
const _this = this window.onresize = function(){ _this.width = document.body.clientWidth }2 、在谷歌浏览器中 ,window.onresize会触发两次 ,网上说是谷歌浏览器的bug
解决办法如下 ,设定一个标识
let flag = true window.onresize = function () { if (flag) { console.log(new Date(), 窗口改变了) flag = false } let timeId = setTimeout(() => { flag = true timeId = null // 清除延时定时器 }, 1000) }没使用flag之前
使用之后 ,如下图 ,控制台只打印了一遍
注意在项目中的使用
1 、window.onresize只能在一个组件中使用,如果多个组件调用则会出现覆盖情况 ,所以我的解决方案是在App.vue中使用 ,获取document.documentElement.clientWidth(即浏览器宽度)存放在vuex中,别的组件只需要用computed(计算属性)将vuex的clientWidth获取 ,然后通过watch监听clientWidth的值 ,即可触发组件事件
2 、由于window.onresize是全局事件 ,在其他页面改变界面时也会执行 ,这样可能会出现问题 ,需要在出这个界面时注销window.onresize事件 。
created() { this.$bus.$on(resize, this.$_setTableHeight) window.onresize = function () { console.log(new Date(), 窗口改变了) } }, beforeDestroy() { this.$bus.$off(resize, this.$_setTableHeight) window.onresize = null },注销之后 ,切换到其他页面 ,控制台就不会输出以下信息
window.addEventListener
mounted() { this.$nextTick(() => { this.onDrawLine() window.addEventListener(resize, this.resize()) }) }, beforeDestroy() { console.log(删除了) // 具名函数使用removeEventListener清除 ,但是匿名函数不行 window.removeEventListener(resize, this.resize()) },性能优化
window.onresize 在监听窗口变化时 ,固然起到很好的效果 ,但是对于网页性能消耗过大 。因为html中每个标签的变化 ,都会触发window.onresize 事件 ,比如显示/隐藏某个抽屉 、添加/删除某个div等等,很有可能会造成循环触发和无限制触发 ,于是新推出了另外一个事件**ResizeObserver(对element和svgelement元素进行监听)**
MDN定义如下:
ResizeObserver避免了通过回调函数调整大小时 ,通常创建的无限回调循环和循环依赖项 。它只能通过在后续的帧中处理 DOM 中更深层次的元素来做到这一点 。如果它的实现遵循规范,则应在绘制前和布局后调用 resize 事件 。
MDN示例:https://mdn.github.io/dom-examples/resize-observer/resize-observer-text.html
部分源码如下:
const h1Elem = document.querySelector(h1); const pElem = document.querySelector(p); const divElem = document.querySelector(body > div); const slider = document.querySelector(input[type="range"]); const checkbox = document.querySelector(input[type="checkbox"]); divElem.style.width = 600px; slider.addEventListener(input, () => { divElem.style.width = `${slider.value}px`; }) const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { if (entry.contentBoxSize) { // Firefox implements `contentBoxSize` as a single content rect, rather than an array const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize; h1Elem.style.fontSize = `${Math.max(1.5, contentBoxSize.inlineSize / 200)}rem`; pElem.style.fontSize = `${Math.max(1, contentBoxSize.inlineSize / 600)}rem`; } else { h1Elem.style.fontSize = `${Math.max(1.5, entry.contentRect.width / 200)}rem`; pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`; } } console.log(Size changed); }); resizeObserver.observe(divElem); checkbox.addEventListener(change, () => { if (checkbox.checked) { resizeObserver.observe(divElem); } else { resizeObserver.unobserve(divElem); } });副作用:兼容性不强 ,有些浏览器兼容 ,具体情况见Can I Use
参考链接:
https://www.cnblogs.com/yxysuanfa/p/6878016.html
https://www.jb51.net/article/245030.htm
https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!