前言
当涉及到应用程序中实现实时交互和动态内容更新时,DOM监视器(MutationObserver)成为了一项强大的工具。该API允许开发人员监视DOM树的更改,并在检测到特定更改时触发相应的操作,从而实现各种交互和动态效果。
在本文中,是在AI聊天场景下,利用new MutationObserver实现的局部功能。
场景一
在聊天场景中,实现一个Copy按钮,使用户能够轻松复制相应的聊天消息或代码片段,提升用户体验和操作便利性。
import { useEffect } from 'react';
const useCopyMutationObserver = (callback: (e: MouseEvent) => void) => {
useEffect(() => {
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
const copyBtns = document.querySelectorAll('.copy-btn-code');
// 移除旧的点击事件监听器
copyBtns.forEach((btn) => btn.removeEventListener('click', callback));
// 添加新的点击事件监听器
copyBtns.forEach((btn) => btn.addEventListener('click', callback));
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
return () => observer.disconnect();
}, []);
};
export default useCopyMutationObserver;
在useCopyMutationObserver自定义hook中,创建了一个MutationObserver实例,用于监听.copy-btn-code按钮的点击事件,并在点击时执行传入的回调函数callback。
import { message } from 'antd';
import copy from 'copy-to-clipboard';
import useCopyMutationObserver from '@/hooks/useCopyMutationObserver';
useCopyMutationObserver((e: MouseEvent) => {
e.stopPropagation();
copy(e.target.querySelector('.text').innerHTML || '');
message.success('复制成功');
});
使用该自定义hook useCopyMutationObserver,在回调函数中,首先阻止事件冒泡,然后通过copy-to-clipboard库将目标元素中的文本内容复制到剪贴板,并显示成功消息。
场景二
监视聊天消息容器,以便在新消息到达时自动滚动到最新消息位置,提供流畅的聊天体验并确保始终能够查看最新的对话内容。
import { useEffect, useRef } from 'react';
const Chat = () => {
const messagesEndRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const observer = new MutationObserver((mutationsList) => {
mutationsList.forEach((mutation) => {
if (mutation.type === 'childList')
messagesEndRef?.current?.scrollIntoView({ behavior: 'smooth' });
});
});
const messagesContainer = document.getElementById(
'messages-container',
) as HTMLElement;
observer.observe(messagesContainer, { childList: true });
return () => observer.disconnect();
}, []);
const handleNewMessage = () => {
// 模拟添加新消息
const newMessage = document.createElement('div');
newMessage.textContent = `New Message ${Math.random()}`;
document.getElementById('messages-container')?.appendChild(newMessage);
};
return (
<div
id="messages-container"
style={{ height: '400px', overflowY: 'scroll' }}
>
{/* 消息列表 */}
<div>Message 1</div>
<div>Message 2</div>
<div>Message 3</div>
{/* 滚动到末尾的参考元素 */}
<div ref={messagesEndRef} />
<button type="button" onClick={handleNewMessage}>
新增消息
</button>
</div>
);
};
export default Chat;
在Chat组件中,创建了一个MutationObserver实例,用于监听messages-container中子节点的变化。每当新的聊天消息被添加到messages-container中时,MutationObserver将检测到子节点列表的变化,并通过调用scrollIntoView方法来确保最新的消息始终可见。
上述仅是一个简单的示例,实际项目中需要根据具体需求进行更多的定制和优化。
结语
MutationObserver是一个强大的工具,可以用于监视DOM树的变化。除了在聊天场景中实现自动滚动和复制按钮之外,MutationObserver还可以用于许多其他场景,例如:
- 实时数据更新:当页面中的数据动态变化时,可以使用
MutationObserver监视数据区域,以便在数据更新时立即做出相应的处理。 - 动态内容加载:监视内容区域,当新内容被加载时自动执行特定操作,例如加载更多内容或触发动画效果。
- 实时通知:在需要实时通知用户的场景下,可以监视特定区域的变化,当有新通知时立即展示给用户。
- 图片懒加载:监视页面上图片元素的变化,当图片进入可视区域时再加载图片,以优化页面加载性能。
- 实时搜索:监视搜索框输入的变化,实现实时搜索功能,动态展示搜索结果。
这些只是 MutationObserver 可以应用的一些场景,它的灵活性和强大功能可以在各种情况下利用它来监听DOM变化并做出相应的处理。