Slate.js气球工具栏执行标记操作后定位异常问题求助
解决Slate.js悬浮工具栏标记操作后定位偏移问题
我看了你遇到的问题——在Slate编辑器里切换文本标记(加粗、斜体这类)后,悬浮工具栏的定位直接跑偏了,从你提供的演示里能明显看到这个bug。结合你贴的代码来看,问题出在DOM更新时机和选区位置获取的同步性上。
问题根源
当你点击工具栏按钮切换标记时,Slate会触发onChange更新编辑器状态,紧接着你的withHoverMenu组件会在componentDidUpdate里调用updateMenu计算工具栏位置。但这里有个关键时间差:Slate更新状态后,DOM的重新渲染(比如给文本包裹<strong>/<em>标签)是异步完成的,此时window.getSelection()拿到的还是旧选区的DOM位置,自然会导致工具栏定位错误。
修复方案
我们只需要把获取选区位置的逻辑延迟到DOM更新完成后执行,用requestAnimationFrame就能轻松解决这个问题——它会把回调放到浏览器下一次重绘前执行,确保此时DOM已经完成更新。
修改你的withHoverMenu组件里的updateMenu方法:
updateMenu = () => { const { value } = this.props const menu = this.menu if (!menu) return if (value.isBlurred || value.isEmpty) { menu.removeAttribute('style') return } // 用requestAnimationFrame确保DOM更新后再计算位置 requestAnimationFrame(() => { const selection = window.getSelection() // 额外加个判断,避免选区为空时报错 if (!selection || selection.rangeCount === 0) return const range = selection.getRangeAt(0) const rect = range.getBoundingClientRect() menu.style.opacity = 1 menu.style.top = `${rect.top + window.scrollY - menu.offsetHeight}px` menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px` }) }
额外优化建议
- 加上
selection和rangeCount的判断,避免极端情况下(比如选区被快速清空)出现控制台报错; - 如果你的编辑器嵌套在有滚动的容器里,建议参考官方示例,加上编辑器容器的
getBoundingClientRect()来计算相对位置,避免容器滚动时工具栏定位偏移。
这样修改后,你再测试标记切换操作,工具栏的定位应该就会和初始选择文本时一样流畅准确了。
内容的提问来源于stack exchange,提问作者Onur Özkan
相关产品推荐
相关产品推荐

