antvis / G

💥 A flexible rendering engine for visualization.
https://g.antv.antgroup.com/
1.07k stars 198 forks source link

[g-lite] 事件处理陷入无限循环,导致页面假死 #1725

Closed wulianpu closed 2 months ago

wulianpu commented 3 months ago

问题描述:

事件处理代码见:https://github.com/antvis/G/blob/ffdef423496adc3b663f9fa3eb70da53d76931d0/packages/g-lite/src/services/EventService.ts#L386-L400 如果 leaveEvent.target 不是Node,就会导致一直在循环

复现方式:

CodeSandbox:https://codesandbox.io/p/devbox/g6-demo-vue3-9w9pjz

预览地址:https://9w9pjz-5173.csb.app/

多点几次节点就可以复现问题了 image

问题应该是使用了 Ref包装的 Graph 对象的原因

wang1212 commented 2 months ago

问题的准确复现路径为:

  1. 选中一个矩形;
  2. 再选中另一个矩形;
  3. 在选中的矩形上开始拖动交互

你可以将示例代码做如下调整,问题即可消失:

-const graphInstance = ref<Graph | null>(null);
+const graphInstance = {value: null as Graph | null};

在依赖 vue 的业务应用中,应避免将 ref 赋值为大数据量级且频繁更新的对象,通常此类对象对应的是可视化组件库/工具库/框架的实例对象。

参考 vue 官方文档中关于深度响应式的解释:https://vuejs.org/guide/essentials/reactivity-fundamentals.html#deep-reactivity

提供的示例在控制台报错后之所以会导致页面失去响应,根本原因是鼠标快速拖动交互过程中,G 内部会频繁的更新对象属性,而 vue 的 ref 会跟踪这些更改并进行一些逻辑处理。