使用 MutationObserver 检测滚动高度变化?
Posted
技术标签:
【中文标题】使用 MutationObserver 检测滚动高度变化?【英文标题】:Detect scrollHeight change with MutationObserver? 【发布时间】:2017-11-09 17:38:15 【问题描述】:如何使用MutationObserver
检测 DOM 元素上的 scrollHeight
何时更改?它不是属性,也不是数据。
背景:我需要检测滚动条何时出现在我的内容元素上,其中overflow-y
设置为自动。我想在滚动条出现的那一刻,scrollHeight
的值会从 0 跳到比如说 500,所以我的想法是设置一个MutationObserver
来检测这个属性的变化。
到目前为止我得到了什么:
HTML
<div class="body" #body>
CSS
.body
overflow-y: auto;
TypeScript
export class MyWatchedContent implements AfterViewInit, OnDestroy
@ViewChild('body', read: ElementRef )
private body: ElementRef;
private observer: MutationObserver;
public ngAfterViewInit()
this.observer = new MutationObserver(this.observerChanges);
this.observer.observe(this.body.nativeElement,
attributes: true,
);
public ngOnDestroy()
this.observer.disconnect();
private observerChanges(records: MutationRecord[], observer: MutationObserver)
console.log('##### MUTATION');
records.forEach((_record) =>
console.log(_record);
);
例如,如果我更改开发者窗口中的背景颜色,我可以看到观察者正在触发
突变my-content-watcher.component.ts?d0f4:233 MutationRecord type: "attributes", target: div.body, addedNodes: NodeList(0), removedNodes: NodeList(0), previousSibling: null…
但是,如果我更改窗口大小以使滚动条出现,则没有检测到突变。这对MutationObserver
是否可行?如果可以,如何?
【问题讨论】:
MutationObserver 不会检测到它。尝试 ResizeObserver 或只是定期检查。 @wOxxOm 甚至 ResizeObserver 都没有检测到 scrollHeight 的变化。 嗯,IntersectionObserver 可能会有所帮助。 ResizeObserver 可能无法检测 scrollHeight,但它会检测内容高度。如果您正在观看会增长的内容本身,应该可以使用它。 【参考方案1】:以下是答案,适合仍在寻找解决方案的任何人:
截至今天,无法直接监控元素的 scrollHeight 变化。
MutationObserver 检测 DOM 树中的变化,这可能表明 scrollHeight 发生了变化,但这是一个疯狂的猜测。 ResizeObserver 检测元素外部高度的变化,但不检测滚动高度(即“内部”高度)。 目前还没有但解决方案非常接近:
解决方案
ResizeObserver 检测元素外部高度的变化...
观察滚动容器没有意义,因为它的外部高度没有改变。改变其出高度的元素是容器的任何 CHILD 节点!
一旦子节点的高度发生变化,就意味着父容器的scrollHeight发生了变化。
原生 JS 版本
const container = document.querySelector('.scrollable-container');
const observer = new ResizeObserver(function()
console.log('New scrollHeight', container.scrollHeight);
);
// This is the critical part: We observe the size of all children!
for (var i = 0; i < container.children.length; i++)
observer.observe(container.children[i]);
)
jQuery 版本
const container = $('.scrollable-container');
const observer = new ResizeObserver(function()
console.log('New scrollHeight', container[0].scrollHeight);
);
container.children().each(function(index, child)
observer.observe(child);
);
进一步的步骤
当子节点被动态添加时,您可以添加一个 MutationObserver 以便在添加新子节点后将其添加到 ResizeObserver。
【讨论】:
元素可能具有动态内容,这意味着动态添加/删除子项。最好将ResizeObserver
与MutationObserver
结合使用,以涵盖内部内容更改和容器实际大小调整的所有情况【参考方案2】:
您可以通过在contenteditable
元素上添加一个内部包装元素(例如span
)来模拟此行为,然后在内部元素上添加ResizeObserver
侦听器。内部span
必须是display:block
否则不会触发ResizeObserver
。
html
<div contenteditable id="input"><span id="content">Some content</span></div>
CSS
#input
max-height: 100px;
overflow: scroll;
white-space: pre-wrap;
#content
display: block;
white-space: pre-wrap;
JS
const content = document.getElementById("content");
const observer = new ResizeObserver((entries) =>
for (const entry of entries)
console.warn(entry);
);
observer.observe(content);
【讨论】:
以上是关于使用 MutationObserver 检测滚动高度变化?的主要内容,如果未能解决你的问题,请参考以下文章
MutationObserver 在整个 DOM 中检测节点的性能
javascript 检测dom变化#MutationObserver #js
javascript 检测dom变化#MutationObserver #js