You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
---原始邮件---
发件人: ***@***.***>
发送时间: 2024年6月4日(周二) 晚上8:26
收件人: ***@***.***>;
抄送: ***@***.******@***.***>;
主题: Re: [yinguangyao/blog] 腾讯文档智能表格渲染层 Feature 设计 (Issue #83)
如果使用 redux 模式,会不会很繁琐
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
1. 前言
腾讯文档智能表格的界面是用 Canvas 进行绘制的,这部分称为 Canvas 渲染层。
出于性能的考虑,这里采用了双层 Canvas 的形式,将频繁变化的内容和不常变化的内容进行了分层。
image.png-29.5kB
如上图所示,表格部分如果没有编辑的话,一般情况下是不需要重绘的,而选区是容易频繁改变的部分。
也有一些竞品将选区用 DOM 来实现,这样也是一种分层,但对于全面拥抱 Canvas 的我们来说不是个很好的实践。
我们将背景不变的部分称为 BoardCanvas,和交互相关的 Canvas 称为 Feature Canvas。
今天主要简单来讲一下 Feature Canvas 这层的设计。
2. 插件化
首先,如何来定义 Feature 这个概念呢?在我们看来,所有和用户交互相关的都是 Feature,比如选区、选中态、hover 阴影、行列移动、智能填充等等。
这一层允许它频繁变化,因为绘制的内容比较有限,重绘的成本明显小于背景部分的绘制。
Kapture 2023-01-07 at 13.30.01.gif-380kB
这些 Feature 又该怎么去管理呢?需要有一套固定的模板来规范它们的代码组织。
因此,我们提倡使用插件化的形式来开发,每个 Feature 都是一个插件类,它拥有自己的生命周期,包括
bootstrap
、updated
、destroy
、addActivedEvents
、removeActivedEvents
等。有了这些钩子之后,每个 Feature 类就会比较固定且规范了。
假设我们需要实现一个功能,点击某个单元格,让这个单元格的背景高亮显示,该怎么做呢?
这里使用 Konva 这个 Canvas 库来简单写一个 Demo:
从上方的示例可以看到,一个 Feature 的开发非常简单,那么插件要怎么注册呢?
在一个统一的入口处,可以将需要注册的插件引入进来一次性注册。
这样一个简单的插件机制就已经完成了,管理起来也相当方便快捷。
3. 数据驱动
在交互中往往伴随着很多状态的产生,最初这些状态是维护在 Feature 中的,如果需要在外部访问状态或者修改 UI,就要使用
getFeature('xxx').yyy
的形式,这是一种不合理的设计。举个例子,我想要知道上面的高亮单元格是哪个,那么要怎么获取呢?
那如果想要复用这个 Feature 来高亮具体的单元格,要怎么做呢?
仔细观察这里面存在的几个问题:
如果开发过 React/Vue,都会想到这里需要做的就是实现一个 Model 层,专门存放这些中间状态。
其次要建立 Model 和 Feature 的关联,实现修改 Model 就会触发 Feature UI 更新的机制,这样就不需要从 Feature 上获取数据和修改 UI 了。
这里选用了 Mobx 来做状态管理,因为它可以很方便的实现我们想要的效果。
那么在 Feature 中如何使用呢?可以基于 Mobx 封装
observer
、watch
两个装饰器方便调用。至于
observer
和watch
的实现也很简单。watch
装饰器用于监听属性的变化,从而执行被装饰的方法。那这里为什么还需要
observer
呢?因为通过装饰器无法获取到类的实例,所以将$watchers
先挂载到原型上面,再通过 observer 拦截构造函数,进而去执行所有的$watchers
,这样就可以将挂载到类上的 Model 实例传进去。使用 Mobx 改造之后,避免了直接获取 Feature 内部的数据,或者调用 Feature 暴露的修改 UI 方法,让整体流程更加清晰直观了。
4. 总结
这里只是对渲染层 Feature Canvas 插件机制的一个小总结,基于 Mobx 我们可以实现很多东西,让整体架构更加清晰简洁。
The text was updated successfully, but these errors were encountered: