有时候我们会遇到监听iframe或document的滚动事件不起作用的情况,在排除代码写错的情况下,我们应该考虑此时的document是否可以滑动。
1、为什么document不能监听滑动?
就很奇怪,明明页面时有滚动条的,为什么说document不可滑动呢?
因为有的document.scrollingElement本身就不可滑动,可滑动的是它的子元素,而不document.scrollingElement本身,document.scrollingElement本身没有溢出问题,它的子元素有溢出问题并产生的scrollbar
展示document不能滚动的DEMO:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>document不能滑动,滑动的是它的子元素</title>
<style>
html,
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div style="width: 100%;height: 100vh;overflow: auto;">
<h1>这是1号标题</h1>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h2>这是2号标题</h2>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h3>这是3号标题</h3>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h4>这是4号标题</h4>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h5>这是5号标题</h5>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h6>这是6号标题</h6>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
</div>
</body>
<script>
window.onload = function() {
document.onscroll = function() {
//获取滚动条的位置
var scrollTop =
document.documentElement.scrollTop ||
document.body.scrollTop;
console.log("滚动条的位置:", scrollTop);
};
};
</script>
</html>
2、什么是document.scrollingElement
scrollingElement(Document 的只读属性)返回滚动文档的 Element 对象的引用。在标准模式下,这是文档的根元素, document.documentElement。
当在怪异模式下,scrollingElement 属性返回 HTML body 元素(若不存在返回 null)。
3、为什么要有document.scrollingElement?
众所周知,获取浏览器高度是有兼容的,当我们需要设置滚动条的位置时,一般情况下:
document.documentElement.scrollTop = 100; // PC端
document.body.scrollTop = 100; // 移动端
当有了document.scrollingElement后我们就不需要处理兼容问题了,两端通用
document.scrollingElement = 100; // 两端通用
Polyfill:https://github.com/mathiasbynens/document.scrollingElement
引入scrollingelement.js可以兼容到下一个版本
4、用js代码测试元素是否可滑动
// 判断是否可滑动
function isScrollable(ele) {
const hasScrollableContent = ele.scrollHeight > ele.clientHeight;
const overflowYStyle = window.getComputedStyle(ele).overflowY;
const isOverflowHidden = overflowYStyle.indexOf('hidden') !== -1;
return hasScrollableContent && !isOverflowHidden;
}
5、监听iframe的滚动案例
5.1 document可滑动
demo.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>iframe或document监听滚动事件</title>
</head>
<body>
<iframe id="myframeId" src="./iframe.html" width="90%" height="200px">
<p>你的浏览器不支持iframes。</p>
</iframe>
</body>
<script>
// 判断是否可滑动
function isScrollable(ele) {
const hasScrollableContent = ele.scrollHeight > ele.clientHeight;
const overflowYStyle = window.getComputedStyle(ele).overflowY;
const isOverflowHidden = overflowYStyle.indexOf('hidden') !== -1;
return hasScrollableContent && !isOverflowHidden;
}
window.onload = function() {
let result = isScrollable(document.scrollingElement);
console.log("demo是否可滑动:", result)
var frameWidow = document.getElementById("myframeId").contentWindow;
console.log(frameWidow);
// 两端通用
// frameWidow.document.scrollingElement.scrollTop = 100
// 适用PC端
// frameWidow.document.documentElement.scrollTop = 200
// 适用移动端
// frameWidow.document.body.scrollTop = 300
// scrollTo()方法
frameWidow.scrollTo(0, 400)
//监听
frameWidow.onscroll = function() {
//获取滚动条的位置
var scrollTop =
frameWidow.document.documentElement.scrollTop ||
frameWidow.document.body.scrollTop;
console.log("frame滚动条的位置:", scrollTop);
// window.pageYOffset (支持IE9+)
// var scrollTop = frameWidow.pageYOffset;
// var scrollTop = frameWidow.document.scrollingElement.scrollTop;
};
};
</script>
</html>
frame.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>iframe或document监听滚动事件</title>
<style>
html,
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<h1>这是1号标题</h1>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h2>这是2号标题</h2>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h3>这是3号标题</h3>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h4>这是4号标题</h4>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h5>这是5号标题</h5>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h6>这是6号标题</h6>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
</body>
<script>
// 判断是否可滑动
function isScrollable(ele) {
const hasScrollableContent = ele.scrollHeight > ele.clientHeight;
const overflowYStyle = window.getComputedStyle(ele).overflowY;
const isOverflowHidden = overflowYStyle.indexOf('hidden') !== -1;
return hasScrollableContent && !isOverflowHidden;
}
window.onload = function() {
console.log(document.scrollingElement)
let result = isScrollable(document.scrollingElement);
console.log("frame是否可滑动:", result)
setTimeout(() => {
// 两端通用
// document.scrollingElement.scrollTop = 100
// 适用PC端
// frameWidow.document.documentElement.scrollTop = 200
// 适用移动端
// frameWidow.document.body.scrollTop = 300
// scrollTo()方法
// frameWidow.scrollTo(0, 400)
})
};
</script>
</html>
5.2 document本身不可滑动
demo.html 不作修改,frame.html 修改如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>iframe或document监听滚动事件</title>
<style>
html,
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div style="width: 100%;height: 100vh;overflow: auto;">
<h1>这是1号标题</h1>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h2>这是2号标题</h2>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h3>这是3号标题</h3>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h4>这是4号标题</h4>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h5>这是5号标题</h5>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<h6>这是6号标题</h6>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>
</div>
</body>
<script>
// 判断是否可滑动
function isScrollable(ele) {
const hasScrollableContent = ele.scrollHeight > ele.clientHeight;
const overflowYStyle = window.getComputedStyle(ele).overflowY;
const isOverflowHidden = overflowYStyle.indexOf('hidden') !== -1;
return hasScrollableContent && !isOverflowHidden;
}
window.onload = function() {
console.log(document.scrollingElement)
let result = isScrollable(document.scrollingElement);
console.log("frame是否可滑动:", result)
setTimeout(() => {
// 两端通用
// document.scrollingElement.scrollTop = 100
// 适用PC端
// frameWidow.document.documentElement.scrollTop = 200
// 适用移动端
// frameWidow.document.body.scrollTop = 300
// scrollTo()方法
// frameWidow.scrollTo(0, 400)
})
};
</script>
</html>