vue中监听iframe的高度来实现自适应
在上一篇文章中说明了如何iframe的父子级之间如何传递信息,但是获取iframe子页面滚动高度的效果并不是很理想。可能出现的问题:1.特殊场景下会出现双重滚动条,影响体验2.即时是加了setTimeout()定时器函数,有的时候也不能够取得准确的scrollHeight的值,例如iframe子页面有很多图片,图片加载过程就会影响到页面的高度。优化:考虑到上述问题,开始寻求其他方式来监听ifram
在上一篇文章中说明了如何iframe的父子级之间如何传递信息,但是获取iframe子页面滚动高度的效果并不是很理想。
可能出现的问题:
1.特殊场景下会出现双重滚动条,影响体验
2.即时是加了setTimeout()定时器函数,有的时候也不能够取得准确的scrollHeight的值,例如iframe子页面有很多图片,图片加载过程就会影响到页面的高度。
优化:
考虑到上述问题,开始寻求其他方式来监听iframe子页面的滚动高度值。
经大神提点,建议在iframe子页面中监听整个页面容器的高度,类似于监听div的高度变化,每次变化都向firame父页面传递高度值。找到了两个API:
MutationObserver
本以为这就好用了,网上很多文章也说的很详细,比如 HTML5新特性之Mutation Observer,可监听到子元素的变动、属性的变动、文本的变动等等,这就给我一种错觉,它可以监听到div的宽高,所以我花了很长时间来调这个东西,上代码,这个是iframe的子页面中写的
mounted() {
this.observed()
},
methods: {
observed() {
var targetNode = document.getElementById('currentContainer');
var config = { attributes: true, childList: true, characterData: true, subtree: true };
var recordHeight = 0;
var mutationObserver = new MutationObserver(function (mutations) {
console.log(mutations);
let height = getComputedStyle(targetNode).getPropertyValue('height')
if(height == recordHeight){
return
}
recordHeight = height
console.log("高度发生变化", document.body.scrollHeight, recordHeight)
window.parent.postMessage(document.body.scrollHeight, "/");
})
mutationObserver.observe(targetNode, config)
}
}
我感觉本身写的没有问题,但就是不好使,继续在网上找资料。。。
直到我看到了这篇文章,html5 mutation observer 不能监听元素尺寸变化,还有何用?,这里提到了ResizeObserver,拯救了我!!!
ResizeObserver
这回不直接往vue里写了,先写个测试,添加了防抖,可能用节流会更好一些,这个防抖携带argument的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>123</title>
<style>
.box {
width: 200px;
height: 20vh;
border: 1px solid red;
}
</style>
</head>
<body>
<div id="ss" class="box"></div>
<script>
function debounce(func, wait) {
let timer;
return function () {
let context = this; // 注意 this 指向
let args = arguments; // arguments中存着e
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args)
}, wait)
}
}
function addResizeListen(dom, callback) {
new ResizeObserver(entries => {
if (callback) callback(entries)
}).observe(dom);
}
addResizeListen(document.getElementById('ss'), debounce((entries) => {
for (let entry of entries) {
console.log(Math.round(entries[0].contentRect.height));
}
}, 500))
</script>
</body>
</html>
呕吼,发现好用,赶紧放到vue里面,也就是iframe的子页面中
mounted() {
this.addResizeListen(
document.getElementById("currentContainer"),
this.debounce((entries) => {
for (let entry of entries) {
let height = Math.round(entries[0].contentRect.height + 570);
window.parent.postMessage(document.body.scrollHeight, "/");
}
}, 500)
);
},
methods: {
addResizeListen(dom, callback) {
new ResizeObserver((entries) => {
if (callback) callback(entries);
}).observe(dom);
},
debounce(func, wait) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, wait);
};
},
},
然后再禁用一下iframe子页面的滚动条
body
overflow-x hidden
overflow-y hidden
打包测试,完美! 万岁!!!
更多推荐
所有评论(0)