Office-js中点击内容控件或高亮文本触发函数的实现方法
实现Word文档反向交互功能(点击文本/内容控件联动加载项面板)
核心逻辑
要完成文档到加载项面板的反向联动,需分两步:监听文档内目标元素的选中/点击事件,再通过事件回调同步更新React面板的滚动与高亮状态。
具体实现步骤
1. 监听文档内的目标元素事件
针对Content Control的监听
利用Word JS API的ContentControlSelectionChanged事件绑定全局监听:
// 加载项初始化时注册事件 async function registerContentControlListeners() { await Word.run(async (context) => { context.document.contentControls.onSelectionChanged.add(onContentControlSelected); await context.sync(); }); } // 选中事件回调 async function onContentControlSelected(event: Word.ContentControlSelectionChangedEventArgs) { const contentControl = event.contentControl; await Word.run(async (context) => { contentControl.load('tag'); // 用tag存储与面板列表项对应的唯一标识 await context.sync(); // 给React组件发送通知 window.postMessage({ type: 'CONTENT_CONTROL_SELECTED', id: contentControl.tag }, '*'); }); }
针对高亮文本的监听
高亮文本一般通过字体背景色标记,需监听文档SelectionChanged事件并判断选中区域是否为高亮文本:
// 注册选中事件监听 async function registerSelectionListeners() { await Word.run(async (context) => { context.document.onSelectionChanged.add(onDocumentSelectionChanged); await context.sync(); }); } // 文档选中变化回调 async function onDocumentSelectionChanged(event: Word.SelectionChangedEventArgs) { const selection = event.selection; await Word.run(async (context) => { selection.load('font/highlightColor'); await context.sync(); // 假设高亮色为黄色#FFFF00,判断选中区域是否为高亮文本 if (selection.font.highlightColor === '#FFFF00') { // 读取高亮文本绑定的自定义属性(提前存储面板项标识) const customProps = selection.getRange().customProperties; customProps.load('items'); await context.sync(); const targetId = customProps.items.find(prop => prop.key === 'panelItemId')?.value; if (targetId) { window.postMessage({ type: 'HIGHLIGHT_TEXT_SELECTED', id: targetId }, '*'); } } }); }
2. React面板接收事件并更新状态
在React组件中监听message事件,收到通知后滚动到对应列表项并高亮:
import { useEffect, useRef } from 'react'; function PanelList({ items }) { const itemRefs = useRef<Record<string, HTMLDivElement | null>>({}); useEffect(() => { const handleMessage = (event: MessageEvent) => { if (['CONTENT_CONTROL_SELECTED', 'HIGHLIGHT_TEXT_SELECTED'].includes(event.data.type)) { const targetId = event.data.id; const targetElement = itemRefs.current[targetId]; if (targetElement) { // 平滑滚动到目标项 targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); // 添加高亮样式 targetElement.classList.add('highlighted'); // 3秒后自动移除高亮(可选) setTimeout(() => targetElement.classList.remove('highlighted'), 3000); } } }; window.addEventListener('message', handleMessage); return () => window.removeEventListener('message', handleMessage); }, []); return ( <div className="panel-list"> {items.map(item => ( <div key={item.id} ref={el => itemRefs.current[item.id] = el} className="list-item" > {item.title} </div> ))} </div> ); }
3. 关键注意事项
- 标识同步:必须保证文档内的Content Control/高亮文本,与面板列表项有一一对应的唯一标识(如
tag或自定义属性),这是联动的核心依据。 - 上下文规范:所有Word API操作必须包裹在
Word.run异步函数中,确保获取正确的文档上下文。 - 事件清理:加载项卸载时要移除注册的事件监听器,避免内存泄漏:
async function unregisterListeners() { await Word.run(async (context) => { context.document.contentControls.onSelectionChanged.remove(onContentControlSelected); context.document.onSelectionChanged.remove(onDocumentSelectionChanged); await context.sync(); }); }
内容的提问来源于stack exchange,提问作者Pooja M
相关产品推荐
相关产品推荐

